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  }