Skip to content

Commit d412847

Browse files
reximKam1k4dze
andcommitted
Port the ytt generator from SubChat
Co-authored-by: Kamikadze <40305144+Kam1k4dze@users.noreply.github.com>
1 parent 636d313 commit d412847

3 files changed

Lines changed: 627 additions & 1 deletion

File tree

markut.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1004,7 +1004,8 @@ var Subcommands = map[string]Subcommand{
10041004
Run: func(name string, args []string) bool {
10051005
chatFlag := flag.NewFlagSet(name, flag.ContinueOnError)
10061006
markutPtr := chatFlag.String("markut", "MARKUT", "Path to the MARKUT file")
1007-
csvPtr := chatFlag.Bool("csv", false, "Generate the chat using the stupid Twich Chat Downloader CSV format. You can then feed this output to tools like SubChat https://github.com/Kam1k4dze/SubChat")
1007+
csvPtr := chatFlag.Bool("csv", false, "Generate the chat in the stupid Twich Chat Downloader CSV format. You can then feed this output to tools like SubChat https://github.com/Kam1k4dze/SubChat")
1008+
yttPtr := chatFlag.Bool("ytt", false, "Generate the chat in ytt format using the SubChat's algorithm: https://github.com/Kam1k4dze/SubChat")
10081009

10091010
err := chatFlag.Parse(args)
10101011

@@ -1017,6 +1018,12 @@ var Subcommands = map[string]Subcommand{
10171018
return false
10181019
}
10191020

1021+
// It's kinda stupid, but I also want to kinda preserve backward compatibility with my reflexes - rexim
1022+
if *csvPtr && *yttPtr {
1023+
fmt.Printf("ERROR: -csv and -ytt cannot be enabled simultaneously\n")
1024+
return false
1025+
}
1026+
10201027
context, ok := defaultContext()
10211028
ok = ok && context.evalMarkutFile(nil, *markutPtr, false) && context.finishEval()
10221029
if !ok {
@@ -1035,6 +1042,32 @@ var Subcommands = map[string]Subcommand{
10351042
}
10361043
cursor += chunk.End - chunk.Start
10371044
}
1045+
} else if *yttPtr {
1046+
chat := []YttChatMessage{}
1047+
var cursor Millis = 0
1048+
for _, chunk := range context.chunks {
1049+
for _, messageGroup := range chunk.ChatLog {
1050+
timestamp := cursor + messageGroup.TimeOffset - chunk.Start
1051+
for _, message := range messageGroup.Messages {
1052+
chat = append(chat, YttChatMessage{
1053+
time: timestamp,
1054+
user: User{
1055+
name: message.Nickname,
1056+
color: parseHexColor(message.Color),
1057+
},
1058+
message: message.Text,
1059+
})
1060+
}
1061+
}
1062+
cursor += chunk.End - chunk.Start
1063+
}
1064+
1065+
params := DefaultChatParams
1066+
xml := generateXML(generateBatches(chat, params), params)
1067+
outputPath := "chat.ytt"
1068+
ioutil.WriteFile(outputPath, []byte(xml), 0644)
1069+
fmt.Printf("Generated %v\n", outputPath)
1070+
// fmt.Print(xml)
10381071
} else {
10391072
capacity := 1
10401073
ring := []ChatMessageGroup{}

xml.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Mimics API of tinyxml2
2+
package main
3+
4+
import (
5+
"log"
6+
"strings"
7+
)
8+
9+
const XMLTrace = false
10+
11+
type XMLDocument struct {
12+
root XMLNode
13+
}
14+
15+
type XMLNode interface {
16+
Print(sb *strings.Builder, level int)
17+
}
18+
19+
type XMLElement struct {
20+
name string
21+
attributes map[string]string
22+
children []XMLNode
23+
}
24+
25+
func (element *XMLElement) Print(sb *strings.Builder, level int) {
26+
sb.WriteString("<")
27+
sb.WriteString(element.name)
28+
for name, value := range element.attributes {
29+
sb.WriteString(" ")
30+
sb.WriteString(name)
31+
sb.WriteString("=")
32+
sb.WriteString("\"")
33+
WriteXmlEscapedStringIntoBuilder(sb, value)
34+
sb.WriteString("\"")
35+
}
36+
if len(element.children) == 0 {
37+
sb.WriteString("/>")
38+
return
39+
}
40+
sb.WriteString(">")
41+
for _, child := range element.children {
42+
child.Print(sb, level + 1)
43+
}
44+
sb.WriteString("</")
45+
sb.WriteString(element.name)
46+
sb.WriteString(">")
47+
}
48+
49+
type XMLText struct {
50+
value string
51+
}
52+
53+
func WriteXmlEscapedStringIntoBuilder(sb *strings.Builder, s string) {
54+
for _, x := range s {
55+
// https://stackoverflow.com/a/1091955
56+
switch x {
57+
case '"': sb.WriteString("&quot;");
58+
case '&': sb.WriteString("&amp;");
59+
case '\'': sb.WriteString("&apos;");
60+
case '<': sb.WriteString("&lt;");
61+
case '>': sb.WriteString("&gt;");
62+
default: sb.WriteRune(x);
63+
}
64+
}
65+
}
66+
67+
func (text *XMLText) Print(sb *strings.Builder, level int) {
68+
WriteXmlEscapedStringIntoBuilder(sb, text.value)
69+
}
70+
71+
func (doc *XMLDocument) NewElement(name string) *XMLElement {
72+
if XMLTrace {
73+
log.Printf("XMLTrace: XMLDocument.NewElement(name = %#v)\n", name)
74+
}
75+
element := new(XMLElement)
76+
element.name = name
77+
element.attributes = map[string]string{}
78+
return element
79+
}
80+
81+
func (doc *XMLDocument) NewText(value string) *XMLText {
82+
if XMLTrace {
83+
log.Printf("XMLTrace: XMLDocument.NewText(value = %#v)\n", value)
84+
}
85+
text := new(XMLText)
86+
text.value = value
87+
return text
88+
}
89+
90+
func (doc *XMLDocument) InsertFirstChild(child XMLNode) {
91+
if XMLTrace {
92+
log.Printf("XMLTrace: XMLDocument.InsertFirstChild(child)\n")
93+
}
94+
doc.root = child
95+
}
96+
97+
func (doc *XMLDocument) String() string {
98+
sb := strings.Builder{}
99+
doc.root.Print(&sb, 0)
100+
return sb.String()
101+
}
102+
103+
func (element *XMLElement) SetAttribute(name string, value string) {
104+
if XMLTrace {
105+
log.Printf("XMLTrace: XMLElement.SetAttribute(name = %#v, value = %#v)\n", name, value)
106+
}
107+
element.attributes[name] = value
108+
}
109+
110+
func (element *XMLElement) SetText(value string) {
111+
if XMLTrace {
112+
log.Printf("XMLTrace: XMLElement.SetText(value = %#v)\n", value)
113+
}
114+
if len(element.children) > 0 {
115+
panic("XMLElement.SetText: expected not children")
116+
}
117+
text := new(XMLText)
118+
text.value = value
119+
element.InsertEndChild(text)
120+
}
121+
122+
func (element *XMLElement) InsertEndChild(child XMLNode) {
123+
if XMLTrace {
124+
log.Printf("XMLTrace: XMLElement.InsertEndChild(child)")
125+
}
126+
element.children = append(element.children, child)
127+
}
128+
129+
func (element *XMLElement) LinkEndChild(child XMLNode) {
130+
element.InsertEndChild(child)
131+
}

0 commit comments

Comments
 (0)