github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/topic/feed.go (about) 1 package topic 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strconv" 7 "strings" 8 "sync/atomic" 9 "time" 10 11 "github.com/Mrs4s/MiraiGo/client/pb/channel" 12 "github.com/Mrs4s/MiraiGo/message" 13 "github.com/Mrs4s/MiraiGo/utils" 14 ) 15 16 type ( 17 Feed struct { 18 Id string 19 Title string 20 SubTitle string 21 CreateTime int64 22 Poster *FeedPoster 23 GuildId uint64 24 ChannelId uint64 25 Images []*FeedImageInfo 26 Videos []*FeedVideoInfo 27 Contents []IFeedRichContentElement 28 } 29 30 FeedPoster struct { 31 TinyId uint64 32 TinyIdStr string 33 Nickname string 34 IconUrl string 35 } 36 37 FeedImageInfo struct { 38 FileId string 39 PatternId string 40 Url string 41 Width uint32 42 Height uint32 43 } 44 45 FeedVideoInfo struct { 46 FileId string 47 PatternId string 48 Url string 49 Width uint32 50 Height uint32 51 // CoverImage FeedImageInfo 52 } 53 54 IFeedRichContentElement interface { 55 pack(patternId string, isPatternData bool) content 56 } 57 58 content map[string]any 59 ) 60 61 var globalBlockId int64 62 63 func genBlockId() string { 64 id := atomic.AddInt64(&globalBlockId, 1) 65 return fmt.Sprintf("%v_%v_%v", time.Now().UnixMilli(), utils.RandomStringRange(4, "0123456789"), id) 66 } 67 68 func (f *Feed) ToSendingPayload(selfUin int64) string { 69 c := content{ // todo: support media 70 "images": make([]int, 0), 71 "videos": make([]int, 0), 72 "poster": content{ 73 "id": f.Poster.TinyIdStr, 74 "nick": f.Poster.Nickname, 75 }, 76 "channelInfo": content{ 77 "sign": content{ 78 "guild_id": strconv.FormatUint(f.GuildId, 10), 79 "channel_id": strconv.FormatUint(f.ChannelId, 10), 80 }, 81 }, 82 "title": content{ 83 "contents": []content{ 84 (&TextElement{Content: f.Title}).pack("", false), 85 }, 86 }, 87 } 88 patternInfo := []content{ 89 { 90 "id": genBlockId(), 91 "type": "blockParagraph", 92 "data": []content{ 93 (&TextElement{Content: f.Title}).pack("", true), 94 }, 95 }, 96 } 97 patternData := make([]content, len(f.Contents)) 98 contents := make([]content, len(f.Contents)) 99 for i, c := range f.Contents { 100 patternId := fmt.Sprintf("o%v_%v_%v", selfUin, time.Now().Format("2006_01_02_15_04_05"), strings.ToLower(utils.RandomStringRange(16, "0123456789abcdef"))) // readCookie("uin")_yyyy_MM_dd_hh_mm_ss_randomHex(16) 101 contents[i] = c.pack(patternId, false) 102 patternData[i] = c.pack(patternId, true) 103 } 104 c["contents"] = content{"contents": contents} 105 patternInfo = append(patternInfo, content{ 106 "id": genBlockId(), 107 "type": "blockParagraph", 108 "data": patternData, 109 }) 110 packedPattern, _ := json.Marshal(patternInfo) 111 c["patternInfo"] = utils.B2S(packedPattern) 112 packedContent, _ := json.Marshal(c) 113 return utils.B2S(packedContent) 114 } 115 116 func DecodeFeed(p *channel.StFeed) *Feed { 117 f := &Feed{ 118 Id: p.Id.Unwrap(), 119 Title: p.Title.Contents[0].TextContent.Text.Unwrap(), 120 SubTitle: "", 121 CreateTime: int64(p.CreateTime.Unwrap()), 122 GuildId: p.ChannelInfo.Sign.GuildId.Unwrap(), 123 ChannelId: p.ChannelInfo.Sign.ChannelId.Unwrap(), 124 } 125 if p.Subtitle != nil && len(p.Subtitle.Contents) > 0 { 126 f.SubTitle = p.Subtitle.Contents[0].TextContent.Text.Unwrap() 127 } 128 if p.Poster != nil { 129 tinyId, _ := strconv.ParseUint(p.Poster.Id.Unwrap(), 10, 64) 130 f.Poster = &FeedPoster{ 131 TinyId: tinyId, 132 TinyIdStr: p.Poster.Id.Unwrap(), 133 Nickname: p.Poster.Nick.Unwrap(), 134 } 135 if p.Poster.Icon != nil { 136 f.Poster.IconUrl = p.Poster.Icon.IconUrl.Unwrap() 137 } 138 } 139 for _, video := range p.Videos { 140 f.Videos = append(f.Videos, &FeedVideoInfo{ 141 FileId: video.FileId.Unwrap(), 142 PatternId: video.PatternId.Unwrap(), 143 Url: video.PlayUrl.Unwrap(), 144 Width: video.Width.Unwrap(), 145 Height: video.Height.Unwrap(), 146 }) 147 } 148 for _, image := range p.Images { 149 f.Images = append(f.Images, &FeedImageInfo{ 150 FileId: image.PicId.Unwrap(), 151 PatternId: image.PatternId.Unwrap(), 152 Url: image.PicUrl.Unwrap(), 153 Width: image.Width.Unwrap(), 154 Height: image.Height.Unwrap(), 155 }) 156 } 157 for _, c := range p.Contents.Contents { 158 if c.TextContent != nil { 159 f.Contents = append(f.Contents, &TextElement{Content: c.TextContent.Text.Unwrap()}) 160 } 161 if c.EmojiContent != nil { 162 id, _ := strconv.ParseInt(c.EmojiContent.Id.Unwrap(), 10, 32) 163 f.Contents = append(f.Contents, &EmojiElement{ 164 Index: int32(id), 165 Id: c.EmojiContent.Id.Unwrap(), 166 Name: message.FaceNameById(int(id)), 167 }) 168 } 169 if c.ChannelContent != nil && c.ChannelContent.ChannelInfo != nil { 170 f.Contents = append(f.Contents, &ChannelQuoteElement{ 171 GuildId: c.ChannelContent.ChannelInfo.Sign.GuildId.Unwrap(), 172 ChannelId: c.ChannelContent.ChannelInfo.Sign.ChannelId.Unwrap(), 173 DisplayText: c.ChannelContent.ChannelInfo.Name.Unwrap(), 174 }) 175 } 176 if c.AtContent != nil && c.AtContent.User != nil { 177 tinyId, _ := strconv.ParseUint(c.AtContent.User.Id.Unwrap(), 10, 64) 178 f.Contents = append(f.Contents, &AtElement{ 179 Id: c.AtContent.User.Id.Unwrap(), 180 TinyId: tinyId, 181 Nickname: c.AtContent.User.Nick.Unwrap(), 182 }) 183 } 184 if c.UrlContent != nil { 185 f.Contents = append(f.Contents, &UrlQuoteElement{ 186 Url: c.UrlContent.Url.Unwrap(), 187 DisplayText: c.UrlContent.DisplayText.Unwrap(), 188 }) 189 } 190 } 191 return f 192 }