Compare commits
4 Commits
v2025.10.3
...
v2025.11.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8f063fd9b | ||
|
|
8b0b53fae7 | ||
|
|
b29c380055 | ||
|
|
cf58a707c7 |
@@ -37,11 +37,9 @@
|
||||
| [LMStudio](https://lmstudio.ai/) | ✅ | 本地大模型运行平台 |
|
||||
| [AnythingLLM](https://anythingllm.com/) | ✅ | 本地知识库 |
|
||||
| [DeepSeek](https://www.deepseek.com/) | ✅ | deepseek-reasoner,deepseek-chat |
|
||||
| [大模型聚合平台](https://cloud.siliconflow.cn/i/foufCerk) | ✅ | 如:[302.AI](https://share.302.ai/1KUpfG),[硅基流动](https://cloud.siliconflow.cn/i/foufCerk),[火山方舟](https://www.volcengine.com/experience/ark?utm_term=202502dsinvite&ac=DSASUQY5&rc=IJSE43PZ) |
|
||||
| [大模型聚合平台](https://cloud.siliconflow.cn/i/foufCerk) | ✅ | 如:[硅基流动](https://cloud.siliconflow.cn/i/foufCerk),[火山方舟](https://www.volcengine.com/experience/ark?utm_term=202502dsinvite&ac=DSASUQY5&rc=IJSE43PZ) |
|
||||
|
||||
### <span style="color: #568DF4;">各位亲爱的朋友们,如果您对这个项目感兴趣,请先给我一个<i style="color: #EA2626;">star</i>吧,谢谢!</span>💕
|
||||
- 302.AI:新用户使用邀请码注册,即可领取 $1 测试额度
|
||||
|
||||
[//]: # (- 优云智算(by UCloud):万卡规模4090免费用10小时,新人注册另增50万tokens,海量热门源项目镜像一键部署,[注册链接](https://www.compshare.cn/image-community?ytag=GPU_YY-gh_gostock))
|
||||
- 火山方舟:新用户每个模型注册即送50万tokens,[注册链接](https://www.volcengine.com/experience/ark?utm_term=202502dsinvite&ac=DSASUQY5&rc=IJSE43PZ)
|
||||
- 硅基流动(siliconflow),注册即送2000万Tokens,[注册链接](https://cloud.siliconflow.cn/i/foufCerk)
|
||||
|
||||
115
app.go
115
app.go
@@ -428,7 +428,8 @@ func (a *App) domReady(ctx context.Context) {
|
||||
a.cronEntrys["MonitorStockPrices"] = id
|
||||
}
|
||||
entryID, err := a.cron.AddFunc(fmt.Sprintf("@every %ds", interval+10), func() {
|
||||
news := data.NewMarketNewsApi().GetNewTelegraph(30)
|
||||
//news := data.NewMarketNewsApi().GetNewTelegraph(30)
|
||||
news := data.NewMarketNewsApi().TelegraphList(30)
|
||||
if config.EnablePushNews {
|
||||
go a.NewsPush(news)
|
||||
}
|
||||
@@ -564,65 +565,84 @@ func (a *App) CheckStockBaseInfo(ctx context.Context) {
|
||||
SetResult(stockBasics).
|
||||
Get("http://8.134.249.145:18080/go-stock/stock_basic.json")
|
||||
|
||||
count := int64(0)
|
||||
db.Dao.Model(&data.StockBasic{}).Count(&count)
|
||||
if count == int64(len(*stockBasics)) {
|
||||
return
|
||||
}
|
||||
for _, stock := range *stockBasics {
|
||||
stockInfo := &data.StockBasic{
|
||||
TsCode: stock.TsCode,
|
||||
Name: stock.Name,
|
||||
Symbol: stock.Symbol,
|
||||
BKCode: stock.BKCode,
|
||||
BKName: stock.BKName,
|
||||
}
|
||||
db.Dao.Model(&data.StockBasic{}).Where("ts_code = ?", stock.TsCode).First(stockInfo)
|
||||
if stockInfo.ID == 0 {
|
||||
db.Dao.Model(&data.StockBasic{}).Create(stockInfo)
|
||||
} else {
|
||||
db.Dao.Model(&data.StockBasic{}).Where("ts_code = ?", stock.TsCode).Updates(stockInfo)
|
||||
}
|
||||
db.Dao.Unscoped().Model(&data.StockBasic{}).Where("1=1").Delete(&data.StockBasic{})
|
||||
err := db.Dao.CreateInBatches(stockBasics, 400).Error
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("保存StockBasic股票基础信息失败:%s", err.Error())
|
||||
}
|
||||
|
||||
//count := int64(0)
|
||||
//db.Dao.Model(&data.StockBasic{}).Count(&count)
|
||||
//if count == int64(len(*stockBasics)) {
|
||||
// return
|
||||
//}
|
||||
//for _, stock := range *stockBasics {
|
||||
// stockInfo := &data.StockBasic{
|
||||
// TsCode: stock.TsCode,
|
||||
// Name: stock.Name,
|
||||
// Symbol: stock.Symbol,
|
||||
// BKCode: stock.BKCode,
|
||||
// BKName: stock.BKName,
|
||||
// }
|
||||
// db.Dao.Model(&data.StockBasic{}).Where("ts_code = ?", stock.TsCode).First(stockInfo)
|
||||
// if stockInfo.ID == 0 {
|
||||
// db.Dao.Model(&data.StockBasic{}).Create(stockInfo)
|
||||
// } else {
|
||||
// db.Dao.Model(&data.StockBasic{}).Where("ts_code = ?", stock.TsCode).Updates(stockInfo)
|
||||
// }
|
||||
//}
|
||||
|
||||
stockHKBasics := &[]models.StockInfoHK{}
|
||||
resty.New().R().
|
||||
SetHeader("user", "go-stock").
|
||||
SetResult(stockHKBasics).
|
||||
Get("http://8.134.249.145:18080/go-stock/stock_base_info_hk.json")
|
||||
for _, stock := range *stockHKBasics {
|
||||
stockInfo := &models.StockInfoHK{
|
||||
Code: stock.Code,
|
||||
Name: stock.Name,
|
||||
BKName: stock.BKName,
|
||||
BKCode: stock.BKCode,
|
||||
}
|
||||
db.Dao.Model(&models.StockInfoHK{}).Where("code = ?", stock.Code).First(stockInfo)
|
||||
if stockInfo.ID == 0 {
|
||||
db.Dao.Model(&models.StockInfoHK{}).Create(stockInfo)
|
||||
} else {
|
||||
db.Dao.Model(&models.StockInfoHK{}).Where("code = ?", stock.Code).Updates(stockInfo)
|
||||
}
|
||||
|
||||
db.Dao.Unscoped().Model(&models.StockInfoHK{}).Where("1=1").Delete(&models.StockInfoHK{})
|
||||
err = db.Dao.CreateInBatches(stockHKBasics, 400).Error
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("保存StockInfoHK股票基础信息失败:%s", err.Error())
|
||||
}
|
||||
|
||||
//for _, stock := range *stockHKBasics {
|
||||
// stockInfo := &models.StockInfoHK{
|
||||
// Code: stock.Code,
|
||||
// Name: stock.Name,
|
||||
// BKName: stock.BKName,
|
||||
// BKCode: stock.BKCode,
|
||||
// }
|
||||
// db.Dao.Model(&models.StockInfoHK{}).Where("code = ?", stock.Code).First(stockInfo)
|
||||
// if stockInfo.ID == 0 {
|
||||
// db.Dao.Model(&models.StockInfoHK{}).Create(stockInfo)
|
||||
// } else {
|
||||
// db.Dao.Model(&models.StockInfoHK{}).Where("code = ?", stock.Code).Updates(stockInfo)
|
||||
// }
|
||||
//}
|
||||
stockUSBasics := &[]models.StockInfoUS{}
|
||||
resty.New().R().
|
||||
SetHeader("user", "go-stock").
|
||||
SetResult(stockUSBasics).
|
||||
Get("http://8.134.249.145:18080/go-stock/stock_base_info_us.json")
|
||||
for _, stock := range *stockUSBasics {
|
||||
stockInfo := &models.StockInfoUS{
|
||||
Code: stock.Code,
|
||||
Name: stock.Name,
|
||||
BKName: stock.BKName,
|
||||
BKCode: stock.BKCode,
|
||||
}
|
||||
db.Dao.Model(&models.StockInfoUS{}).Where("code = ?", stock.Code).First(stockInfo)
|
||||
if stockInfo.ID == 0 {
|
||||
db.Dao.Model(&models.StockInfoUS{}).Create(stockInfo)
|
||||
} else {
|
||||
db.Dao.Model(&models.StockInfoUS{}).Where("code = ?", stock.Code).Updates(stockInfo)
|
||||
}
|
||||
|
||||
db.Dao.Unscoped().Model(&models.StockInfoUS{}).Where("1=1").Delete(&models.StockInfoUS{})
|
||||
err = db.Dao.CreateInBatches(stockUSBasics, 400).Error
|
||||
if err != nil {
|
||||
logger.SugaredLogger.Errorf("保存StockInfoUS股票基础信息失败:%s", err.Error())
|
||||
}
|
||||
//for _, stock := range *stockUSBasics {
|
||||
// stockInfo := &models.StockInfoUS{
|
||||
// Code: stock.Code,
|
||||
// Name: stock.Name,
|
||||
// BKName: stock.BKName,
|
||||
// BKCode: stock.BKCode,
|
||||
// }
|
||||
// db.Dao.Model(&models.StockInfoUS{}).Where("code = ?", stock.Code).First(stockInfo)
|
||||
// if stockInfo.ID == 0 {
|
||||
// db.Dao.Model(&models.StockInfoUS{}).Create(stockInfo)
|
||||
// } else {
|
||||
// db.Dao.Model(&models.StockInfoUS{}).Where("code = ?", stock.Code).Updates(stockInfo)
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
func (a *App) NewsPush(news *[]models.Telegraph) {
|
||||
@@ -1337,7 +1357,8 @@ func (a *App) GetTelegraphList(source string) *[]*models.Telegraph {
|
||||
}
|
||||
|
||||
func (a *App) ReFleshTelegraphList(source string) *[]*models.Telegraph {
|
||||
data.NewMarketNewsApi().GetNewTelegraph(30)
|
||||
//data.NewMarketNewsApi().GetNewTelegraph(30)
|
||||
data.NewMarketNewsApi().TelegraphList(30)
|
||||
data.NewMarketNewsApi().GetSinaNews(30)
|
||||
telegraphs := data.NewMarketNewsApi().GetTelegraphList(source)
|
||||
return telegraphs
|
||||
|
||||
@@ -33,6 +33,70 @@ func NewMarketNewsApi() *MarketNewsApi {
|
||||
return &MarketNewsApi{}
|
||||
}
|
||||
|
||||
func (m MarketNewsApi) TelegraphList(crawlTimeOut int64) *[]models.Telegraph {
|
||||
//https://www.cls.cn/nodeapi/telegraphList
|
||||
url := "https://www.cls.cn/nodeapi/telegraphList"
|
||||
res := map[string]any{}
|
||||
_, _ = resty.New().SetTimeout(time.Duration(crawlTimeOut)*time.Second).R().
|
||||
SetHeader("Referer", "https://www.cls.cn/").
|
||||
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.60").
|
||||
SetResult(&res).
|
||||
Get(url)
|
||||
var telegraphs []models.Telegraph
|
||||
|
||||
if v, _ := convertor.ToInt(res["error"]); v == 0 {
|
||||
data := res["data"].(map[string]any)
|
||||
rollData := data["roll_data"].([]any)
|
||||
for _, v := range rollData {
|
||||
news := v.(map[string]any)
|
||||
ctime, _ := convertor.ToInt(news["ctime"])
|
||||
dataTime := time.Unix(ctime, 0)
|
||||
logger.SugaredLogger.Debugf("dataTime: %s", dataTime)
|
||||
telegraph := models.Telegraph{
|
||||
Content: news["content"].(string),
|
||||
Time: dataTime.Format("15:04:05"),
|
||||
DataTime: &dataTime,
|
||||
Url: news["shareurl"].(string),
|
||||
Source: "财联社电报",
|
||||
IsRed: GetLevel(news["level"].(string)),
|
||||
SentimentResult: AnalyzeSentiment(news["content"].(string)).Description,
|
||||
}
|
||||
cnt := int64(0)
|
||||
db.Dao.Model(telegraph).Where("time=? and content=?", telegraph.Time, telegraph.Content).Count(&cnt)
|
||||
if cnt > 0 {
|
||||
continue
|
||||
}
|
||||
telegraphs = append(telegraphs, telegraph)
|
||||
db.Dao.Model(&models.Telegraph{}).Create(&telegraph)
|
||||
logger.SugaredLogger.Debugf("telegraph: %+v", &telegraph)
|
||||
if news["subjects"] == nil {
|
||||
continue
|
||||
}
|
||||
subjects := news["subjects"].([]any)
|
||||
for _, subject := range subjects {
|
||||
name := subject.(map[string]any)["subject_name"].(string)
|
||||
tag := &models.Tags{
|
||||
Name: name,
|
||||
Type: "subject",
|
||||
}
|
||||
db.Dao.Model(tag).Where("name=? and type=?", name, "subject").FirstOrCreate(&tag)
|
||||
db.Dao.Model(models.TelegraphTags{}).Where("telegraph_id=? and tag_id=?", telegraph.ID, tag.ID).FirstOrCreate(&models.TelegraphTags{
|
||||
TelegraphId: telegraph.ID,
|
||||
TagId: tag.ID,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
//db.Dao.Model(&models.Telegraph{}).Create(&telegraphs)
|
||||
//logger.SugaredLogger.Debugf("telegraphs: %+v", &telegraphs)
|
||||
}
|
||||
|
||||
return &telegraphs
|
||||
}
|
||||
func GetLevel(s string) bool {
|
||||
return s >= "C"
|
||||
}
|
||||
|
||||
func (m MarketNewsApi) GetNewTelegraph(crawlTimeOut int64) *[]models.Telegraph {
|
||||
url := "https://www.cls.cn/telegraph"
|
||||
response, _ := resty.New().SetTimeout(time.Duration(crawlTimeOut)*time.Second).R().
|
||||
@@ -77,7 +141,7 @@ func (m MarketNewsApi) GetNewTelegraph(crawlTimeOut int64) *[]models.Telegraph {
|
||||
if telegraph.Content != "" {
|
||||
telegraph.SentimentResult = AnalyzeSentiment(telegraph.Content).Description
|
||||
cnt := int64(0)
|
||||
db.Dao.Model(telegraph).Where("time=? and source=?", telegraph.Time, telegraph.Source).Count(&cnt)
|
||||
db.Dao.Model(telegraph).Where("time=? and content=?", telegraph.Time, telegraph.Content).Count(&cnt)
|
||||
if cnt == 0 {
|
||||
db.Dao.Create(&telegraph)
|
||||
telegraphs = append(telegraphs, telegraph)
|
||||
@@ -118,6 +182,7 @@ func (m MarketNewsApi) GetNewsList(source string, limit int) *[]*models.Telegrap
|
||||
return news
|
||||
}
|
||||
func (m MarketNewsApi) GetNewsList2(source string, limit int) *[]*models.Telegraph {
|
||||
NewMarketNewsApi().TelegraphList(30)
|
||||
news := &[]*models.Telegraph{}
|
||||
if source != "" {
|
||||
db.Dao.Model(news).Preload("TelegraphTags").Where("source=?", source).Order("id desc,is_red desc").Limit(limit).Find(news)
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/coocood/freecache"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
@@ -38,7 +39,6 @@ func TestGetIndustryRank(t *testing.T) {
|
||||
res := NewMarketNewsApi().GetIndustryRank("0", 10)
|
||||
for s, a := range res["data"].([]any) {
|
||||
logger.SugaredLogger.Debugf("key: %+v, value: %+v", s, a)
|
||||
|
||||
}
|
||||
}
|
||||
func TestGetIndustryMoneyRankSina(t *testing.T) {
|
||||
@@ -234,3 +234,18 @@ func TestInteractiveAnswer(t *testing.T) {
|
||||
logger.SugaredLogger.Debugf(md)
|
||||
|
||||
}
|
||||
func TestGetNewsList2(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
news := NewMarketNewsApi().GetNewsList2("财联社电报", random.RandInt(100, 500))
|
||||
messageText := strings.Builder{}
|
||||
for _, telegraph := range *news {
|
||||
messageText.WriteString("## " + telegraph.Time + ":" + "\n")
|
||||
messageText.WriteString("### " + telegraph.Content + "\n")
|
||||
}
|
||||
logger.SugaredLogger.Debugf("value: %s", messageText.String())
|
||||
}
|
||||
|
||||
func TestTelegraphList(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
NewMarketNewsApi().TelegraphList(30)
|
||||
}
|
||||
|
||||
@@ -323,7 +323,6 @@ func (o *OpenAi) NewSummaryStockNewsStreamWithTools(userQuestion string, sysProm
|
||||
})
|
||||
}()
|
||||
wg.Wait()
|
||||
|
||||
news := NewMarketNewsApi().GetNewsList2("财联社电报", random.RandInt(100, 500))
|
||||
messageText := strings.Builder{}
|
||||
for _, telegraph := range *news {
|
||||
|
||||
@@ -9,6 +9,14 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go-stock/backend/db"
|
||||
"go-stock/backend/logger"
|
||||
"go-stock/backend/models"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/chromedp/chromedp"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
@@ -17,17 +25,10 @@ import (
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/robertkrimen/otto"
|
||||
"github.com/samber/lo"
|
||||
"go-stock/backend/db"
|
||||
"go-stock/backend/logger"
|
||||
"go-stock/backend/models"
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/transform"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/plugin/soft_delete"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const sinaStockUrl = "http://hq.sinajs.cn/rn=%d&list=%s"
|
||||
@@ -1744,6 +1745,11 @@ func (receiver StockDataApi) GetCommonKLineData(stockCode string, kLineType stri
|
||||
return K
|
||||
}
|
||||
|
||||
// GetStockHistoryMoneyData 获取股票历史资金流向数据
|
||||
func (receiver StockDataApi) GetStockHistoryMoneyData() {
|
||||
|
||||
}
|
||||
|
||||
// JSONToMarkdownTable 将JSON数据转换为Markdown表格
|
||||
func JSONToMarkdownTable(jsonData []byte) (string, error) {
|
||||
var data []map[string]interface{}
|
||||
|
||||
@@ -265,3 +265,20 @@ func TestStockDataApi_GetIndexBasic(t *testing.T) {
|
||||
stockDataApi := NewStockDataApi()
|
||||
stockDataApi.GetIndexBasic()
|
||||
}
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
db.Init("../../data/stock.db")
|
||||
|
||||
stockBasics := &[]StockBasic{}
|
||||
resty.New().R().
|
||||
SetHeader("user", "go-stock").
|
||||
SetResult(stockBasics).
|
||||
Get("http://8.134.249.145:18080/go-stock/stock_basic.json")
|
||||
|
||||
db.Dao.Unscoped().Model(&StockBasic{}).Where("1=1").Delete(&StockBasic{})
|
||||
err := db.Dao.CreateInBatches(stockBasics, 400).Error
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -232,6 +232,7 @@ type Prompt struct {
|
||||
type Telegraph struct {
|
||||
gorm.Model
|
||||
Time string `json:"time"`
|
||||
DataTime *time.Time `json:"dataTime"`
|
||||
Content string `json:"content"`
|
||||
SubjectTags []string `json:"subjects" gorm:"-:all"`
|
||||
StocksTags []string `json:"stocks" gorm:"-:all"`
|
||||
@@ -239,7 +240,7 @@ type Telegraph struct {
|
||||
Url string `json:"url"`
|
||||
Source string `json:"source"`
|
||||
TelegraphTags []TelegraphTags `json:"tags" gorm:"-:migration;foreignKey:TelegraphId"`
|
||||
SentimentResult string `json:"sentimentResult" gorm:"-:all"`
|
||||
SentimentResult string `json:"sentimentResult"`
|
||||
}
|
||||
type TelegraphTags struct {
|
||||
gorm.Model
|
||||
|
||||
@@ -49,6 +49,9 @@ const updateMessage = () => {
|
||||
<n-text type="warning">查看原文</n-text>
|
||||
</a>
|
||||
</n-tag>
|
||||
<n-tag v-if="item.sentimentResult" :bordered="false" :type="item.sentimentResult==='看涨'?'error':item.sentimentResult==='看跌'?'success':'info'" size="small">
|
||||
{{ item.sentimentResult }}
|
||||
</n-tag>
|
||||
</n-space>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
|
||||
Reference in New Issue
Block a user