فهرست منبع

Merge pull request #34 from tsoding/actual-chat-rendering

Actual chat rendering
Alexey Kutepov 5 سال پیش
والد
کامیت
48688f25d9
6فایلهای تغییر یافته به همراه981 افزوده شده و 86 حذف شده
  1. 814 0
      569086201.txt
  2. 1 1
      Makefile
  3. 2 0
      src/vodus.cpp
  4. 0 7
      src/vodus_bttv.cpp
  5. 76 78
      src/vodus_main.cpp
  6. 88 0
      src/vodus_string.cpp

+ 814 - 0
569086201.txt

@@ -0,0 +1,814 @@
+[0:00:02] <Tsoding> catDance catDance catDance catDance catDance catDance catDance catDance catDance catDance
+[0:00:08] <ecenti> Dark times have come: 1) corona 2) black hole feels bad in center of Galaxy 3) js on Tsozin stream
+[0:00:22] <oakmrk> catDance catDance catDance catDance catDance catDance catDance catDance
+[0:00:24] <Tsoding> New friends PepeLaughW
+[0:00:38] <IceLeo> waddup corona comrades
+[0:00:40] <igooddoog> Hello, guys! PogChamp
+[0:00:41] <nashesvobodnoye> PogChamp
+[0:00:44] <oakmrk> pepeJAM TeaTime
+[0:00:46] <Tsoding> PogChamp
+[0:00:53] <nashesvobodnoye> PagChomp
+[0:00:53] <ecenti> monkaSoap pepeD pepeD
+[0:00:58] <Tsoding> Who said corona? monkaSoap
+[0:01:02] <nashesvobodnoye> !monkaSoap
+[0:01:02] <MrBotka> https://helep0d.xyz/public/pepe/monkaSoap.gif
+[0:01:36] <IceLeo> Tsoding why no more hopes and dreams?
+[0:01:54] <kolumbetko> monkaSoap tsodinJS
+[0:02:08] <ecenti> isn`t it macrophone, @tsoding ? looks big
+[0:02:13] <Tsoding> monkaSoap tsodinJS getting ready for JavaScript
+[0:02:28] <mateusf777> hello hello!
+[0:02:36] <Tsoding> catDance
+[0:02:52] <lexicalscoped> lexicalscoped subscribed at Tier 1. They've subscribed for 2 months, currently on a 2 month streak! time for tea!
+[0:03:01] <Tsoding> @lexicalscoped, PagChomp
+[0:03:02] <ecenti> TeaTime TeaTime TeaTime
+[0:03:03] <mateusf777> my god!
+[0:03:06] <ditheren> tsodinCool
+[0:03:07] <Tsoding> PagChomp TeaTime
+[0:03:28] <said6289> Hello hello!
+[0:03:36] <ecenti> @said6969 hallo!
+[0:04:05] <ecenti> !nexttrack
+[0:04:12] <mateusf777> catDance TeaTime
+[0:04:21] <donaim> mouse is moving WutFace
+[0:04:22] <said6289> Finally, some epic Javascript programming
+[0:04:29] <ecenti> pepeD pepeD pepeD pepeD
+[0:04:40] <kolumbetko> !where JavaScript
+[0:04:41] <MrBotka> Where did Tsoding learn JavaScript
+[0:04:49] <ecenti> !opa
+[0:04:49] <MrBotka> OPA DAVAI DAVAI SlavPls
+[0:05:01] <lexicalscoped> probably learned javascript writing his own browser in C
+[0:05:07] <lenkense> so all intercity transport has been cancelled here and public transport will only transport people on seats and no more people standing up on the bus
+[0:05:11] <mateusf777> just waiting for the !pop
+[0:05:12] <avetisback> Everquest 3
+[0:05:13] <kolumbetko> Dance Dance DANCE DANCE Dance Dance DANCE DANCE Dance Dance DANCE DANCE
+[0:05:19] <mateusf777> !pop
+[0:05:20] <MrBotka> ҉ pop ҉
+[0:05:27] <ecenti> Dance Dance DANCE DANCE Dance Dance DANCE DANCE Dance Dance DANCE DANCE
+[0:05:46] <lenkense> also no soccer/football
+[0:05:58] <kolumbetko> Kreygasm Dance
+[0:06:06] <ecenti> !jsquarantine
+[0:06:27] <kolumbetko> CoronaScript WutFace
+[0:06:28] <said6289> Learning by implementing SeemsGood @lexicalscoped
+[0:06:49] <said6289> @kolumbetko I think someone needs to make that
+[0:07:00] <Sycode__> yo dude i just got qualified for affiliate and am now waiting for an invitation to the affiliate program PogChamp
+[0:07:03] <IceLeo> RainbowPls RainbowPls RainbowPls RainbowPls RainbowPls RainbowPls RainbowPls RainbowPls RainbowPls RainbowPls
+[0:07:10] <ecenti> peepoRun peepoRun pepeD pepeD pepeJAM pepeJAM monkaSoap
+[0:07:22] <Sycode__> @said6289 i wonder if making coronascript would make js better or worse
+[0:07:40] <IceLeo> what's the javascript meme?
+[0:07:55] <IceLeo> Is he adding JS scripting to his framework?
+[0:07:57] <kolumbetko> Npm bought by M$?
+[0:07:57] <ecenti> they said js vaccine will be ready soon
+[0:08:18] <said6289> Typescript is basically js vaccine :D
+[0:08:22] <kolumbetko> ^
+[0:08:27] <ecenti> KEKW
+[0:09:04] <ecenti> forsenPls DonaldPls forsenPls DonaldPls
+[0:09:14] <Tsoding> ppHop
+[0:09:28] <ecenti> !poop
+[0:09:29] <MrBotka> 💩
+[0:09:33] <igooddoog> PogU
+[0:09:34] <agent_denton> hey
+[0:09:34] <xnorem80> hello
+[0:09:35] <stupremee> !today
+[0:09:36] <MrBotka> Web Application in C. We may do a little bit of JavaScript frontend today PogU. https://github.com/tsoding/skedudle Wash your eyes, don't touch your hands monkaSoap
+[0:09:37] <thepeskypotato> hello
+[0:09:38] <lenkense> dabbing?
+[0:09:56] <mateusf777> my god!
+[0:09:58] <IceLeo> no welcome for me :(
+[0:10:07] <Tsoding> !project
+[0:10:07] <MrBotka> Web Application in C. We may do a little bit of JavaScript frontend today PogU. https://github.com/tsoding/skedudle Wash your eyes, don't touch your hands monkaSoap
+[0:10:11] <lexicalscoped> my company has now flipped policy, we have to submit work from office time if we want to go in office
+[0:10:23] <ecenti> vy no music in background?? PepeHands
+[0:10:25] <chanhuhu> I love vuejs Kappa
+[0:10:31] <mateusf777> because we can!
+[0:10:47] <mateusf777> epic AF!
+[0:12:23] <ecenti> github corona
+[0:12:25] <igooddoog> monkaS
+[0:13:00] <mateusf777> maybe that's the problem
+[0:13:05] <lenkense> someone forked but didn't fork
+[0:13:24] <ecenti> streamer is microphone
+[0:13:32] <vishvafire> why JS? Stay away from that madness!
+[0:13:34] <lenkense> split personality?
+[0:13:50] <kolumbetko> That's the source of js-19 - JSON lib
+[0:15:16] <ecenti> chat, what T-shirt should I buy to identify myself as a Haskell fan?
+[0:15:18] <vishvafire> is the DOM not accessible through WASM?
+[0:16:35] <lastmiles> cheer500 for tea .. and good morning
+[0:17:08] <lexicalscoped> are bits better or worse then straight donos?
+[0:17:17] <lastmiles> far far worse
+[0:17:43] <lexicalscoped> Do they do anything extra? I haven't played with them
+[0:17:51] <vishvafire> i hate the web stack. Whenever anything works, it feels like an accident, whenever anything doesn't still an accident. The architecture of the modern day web feels broken on a deep level
+[0:18:18] <lastmiles> modern web is full of layers of obfuscation and confusion
+[0:18:59] <lenkense> couldn't you make a script/alias that check if the files are there and then call the actual wget?
+[0:19:07] <Manuel_actuallySelfWorker> FutureMan
+[0:19:35] <vishvafire> is this what is called a FQDN?
+[0:19:41] <lenkense> A shell script, I meant
+[0:19:58] <aodhneine> \ AYAYA everyone, how are you feeling today?
+[0:20:16] <igooddoog> aodhneine, Kappa /
+[0:20:23] <aodhneine> \ AYAYA igooddoog
+[0:21:32] <aodhneine> are you still working on the json parser?
+[0:21:36] <Tuxity> A rare example of someone voluntarily programming javascript
+[0:22:31] <aodhneine> karaoke RainbowPls
+[0:23:10] <aodhneine> REEeee use java, abstraction over abstraction, tsoding REEeee
+[0:23:17] <apa420> okidokie
+[0:23:28] <Faceless_Bard> AYAYA everyone /
+[0:23:29] <apa420> apa420Hey
+[0:23:37] <apa420> all my exams can't be held at campus anymore FeelsGoodMan
+[0:23:40] <aodhneine> \ AYAYA Faceless_Bard apa420
+[0:23:43] <apa420> so professors have no idea what to do 4HEad
+[0:23:46] <igooddoog> apa420, PogChamp
+[0:23:48] <Manuel_actuallySelfWorker> SeemsGood
+[0:23:54] <apa420> apa420Hey aodhneine
+[0:23:57] <apa420> apa420Hey igooddoog
+[0:24:29] <apa420> Jsont
+[0:24:53] <aodhneine> you json't do that Kappa
+[0:25:23] <Manuel_actuallySelfWorker> CrreamAwk tsodinCool
+[0:25:37] <apa420> tsodinGasm
+[0:26:05] <aodhneine> tsodinGasm
+[0:26:23] <Manuel_actuallySelfWorker> nice tsodinFeels
+[0:26:24] <apa420> it's pretty cool for c Kapp
+[0:26:44] <nightmonkeyfolkway> This is cool
+[0:29:17] <aodhneine> mappend :: String -> String -> String
+[0:29:57] <vishvafire> Yessssss
+[0:30:07] <vishvafire> variadcs are cool
+[0:30:31] <igooddoog> Pepega
+[0:30:35] <aodhneine> just overload operator+ tsodinW
+[0:30:46] <said6289> Maybe a printf style function?
+[0:31:01] <vishvafire> @aodhneine PogChamp. Linus would be so proud
+[0:31:14] <marko8137> chop chop
+[0:31:26] <marko8137> Privet Aleksey
+[0:31:49] <said6289> You could make your own printf for just your string type
+[0:31:53] <apa420> len + len + len
+[0:32:06] <nulligor> khello
+[0:32:07] <apa420> KKomrade
+[0:32:14] <aodhneine> khalloc
+[0:32:54] <Irazorx0> blin?
+[0:33:20] <vishvafire> @tsoding Can't we typecast the variadic arguments to our String?
+[0:33:32] <apa420> if only you had template for the concat Kapp
+[0:34:19] <marko8137> tsodinFeels
+[0:34:27] <PanosTrak> zdarova
+[0:35:40] <vishvafire> gethostbyname()
+[0:35:53] <nulligor> btw httpie is pretty epic
+[0:36:46] <lenkense> concatening on dynamic memory surely a hard task Kappa
+[0:37:01] <marko8137> Tsoding rewriting electron and the chrome browser :D
+[0:37:08] <marko8137> C Web Framework :D
+[0:37:48] <vishvafire> Could you explain the issues of the variadics?
+[0:39:08] <CopperCasted> PogChamp
+[0:39:14] <lenkense> ah! yes, I know printf is actually a macro to vprintf that actually does that variadic thing, but it's really complex and I don't understand it
+[0:39:33] <aodhneine> \ AYAYA CopperCasted
+[0:39:43] <CopperCasted> \ AYAYA @aodhneine
+[0:41:03] <CopperCasted> tsodinVim_TK
+[0:41:23] <IceLeo> rust doesn't have this problem btw
+[0:41:33] <CopperCasted> !rustify printf
+[0:41:34] <MrBotka> unsafe { printf }
+[0:41:53] <vishvafire> time to contact gcc and clang
+[0:41:54] <lenkense> ah! yes I see, printf is a problem that is fixed but not for "printf-like" functions, great solution Kappa
+[0:42:27] <mateusf777> @IceLeo sure Kappa
+[0:43:41] <vishvafire> software engineering is so great. The first function that any programmer actually learns is an exception that they cannot write themselves. What a disaster
+[0:44:24] <lenkense> fun fact: The wikipedia article on variadic functions does examplifies how C implements variadic
+[0:44:47] <Manuel_actuallySelfWorker> @vishvafire nothing is perfect bro
+[0:44:57] <CopperCasted> shiftClassy Assembly does not have this problem
+[0:45:53] <Manuel_actuallySelfWorker> @coppercasted LUL
+[0:46:10] <vishvafire> why dont the standards fix these problems ??
+[0:46:30] <vishvafire> The ISO C Committee must be aware and have it on their plate right?
+[0:47:34] <CopperCasted> shiftStare Did HolyC fix this?
+[0:48:05] <lenkense> I know I have said this before, but every time you say that the browser querries I imagine firefox reading Queer theory like Judith Butler
+[0:48:37] <lenkense> yes, it's just funny "homophones"
+[0:48:59] <vishvafire> but those systems won't update their compilers right? They could use C11 compliant compiler version
+[0:49:16] <aodhneine> tsodinJS
+[0:49:20] <vishvafire> C20 could fix this and compilers can release an update
+[0:49:21] <iammrrob0t> iammrrob0t subscribed at Tier 1. They've subscribed for 7 months, currently on a 5 month streak! 7 months.
+[0:49:27] <aodhneine> \ AYAYA / iammrrob0t
+[0:49:41] <Manuel_actuallySelfWorker> tumtumChamp
+[0:49:50] <igooddoog> Wow, you can bake anything using this feature PogChamp
+[0:50:20] <iammrrob0t> 🦾😬
+[0:50:32] <aodhneine> text/html
+[0:51:09] <vishvafire> text/html
+[0:51:17] <vishvafire> @aodhneine beat me to it
+[0:51:54] <iammrrob0t> Hahahaha not everybody get the sarcasm hahaha people think I like php 😱
+[0:52:25] <igooddoog> D:
+[0:52:32] <igooddoog> !ban iammrrob0t
+[0:52:32] <MrBotka> iammrrob0t has been banned
+[0:52:34] <aodhneine> !ban iammrrob0t
+[0:52:34] <MrBotka> iammrrob0t has been banned
+[0:52:46] <iammrrob0t> Hahahaha
+[0:52:48] <ayhammamoun> I drink tea without sugur tsodinKomrade
+[0:52:49] <vishvafire> will we make a templating system like Django's templating engine or Jinja2?
+[0:52:58] <Manuel_actuallySelfWorker> MingLee
+[0:53:08] <vishvafire> tsodinJS tsodinJS tsodinJS LuvBlush LuvBlush LuvBlush
+[0:53:10] <igooddoog> marko8137, Jebaited
+[0:53:18] <MrBotka> @xd6912369xd You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[0:53:36] <iammrrob0t> Developers developers developers developers ...
+[0:53:43] <aodhneine> doesn't we already have our own templating engine, used right now for error pages?
+[0:54:00] <vishvafire> please add a defer at the end of script tags @tsoding
+[0:54:31] <TsundereTubeWorm> godlike routing Pog
+[0:54:58] <igooddoog> 4Head
+[0:55:07] <aodhneine> application/javascript
+[0:55:11] <Manuel_actuallySelfWorker> 4Head
+[0:55:20] <vishvafire> text/javascript
+[0:56:05] <MyUsernameFrank> @iammrrob0t the name of the emote is tsodinJS, so it may look like PHP, but it is actually JavaScript :-)
+[0:56:09] <xd6912369xd> Pog
+[0:56:12] <aodhneine> tsodinHyper
+[0:56:14] <thepeskypotato> wow
+[0:56:23] <Manuel_actuallySelfWorker> CurseLit tsodinHyper CurseLit
+[0:56:52] <vishvafire> @aodhneine I thought it's text/javascript?
+[0:57:17] <holysheep_> use axios
+[0:57:28] <TsundereTubeWorm> internet explorer made modern webites TPFufun
+[0:57:39] <aodhneine> vishvafire, see http://www.rfc-editor.org/rfc/rfc4329.txt , page 10
+[0:57:44] <SpiceyCondiment> you take the promise, and shove it up your ass
+[0:57:57] <said6289> LUL
+[0:58:21] <vishvafire> you could use async/await if you used Babel to compile JS gchessWHY. Only JS can be so complex Pog
+[0:58:23] <MrBotka> @spydas02 You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[0:58:26] <ordyH_Hydro> LOL
+[0:58:30] <Cristian_DG> i think you need another "then"
+[0:58:38] <SpiceyCondiment> you have to await the body
+[0:58:41] <MrBotka> @hoffs You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[0:58:41] <aodhneine> fetch().then(x => x.json())
+[0:58:51] <lenkense> A russian is asking me where's the body... Am I going to jail?
+[0:59:00] <SpiceyCondiment> await the fetch
+[0:59:02] <said6289> fetch also performs a "preflight" http OPTIONS request iirc
+[0:59:07] <hoffs> also json() is promise too
+[0:59:11] <igooddoog> PogChamp
+[0:59:12] <sibane> Pog
+[0:59:12] <TsundereTubeWorm> Pog
+[0:59:17] <said6289> ebic
+[0:59:19] <vishvafire> Pog
+[0:59:32] <Manuel_actuallySelfWorker> PagChomp
+[0:59:35] <hoffs> or use async/await
+[0:59:38] <MrBotka> @srgpqt You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[0:59:42] <aodhneine> tsodinHyper
+[0:59:46] <srgpqt> Remove the console log
+[0:59:48] <SpiceyCondiment> never seen console.log used like that before, damn
+[0:59:56] <SpiceyCondiment> ah thats why @srgpqt
+[1:00:19] <vishvafire> @hoffs async/await is not yet supported on all browsers
+[1:00:26] <said6289> You can add a .catch
+[1:00:28] <segfault8> its .catch(...)
+[1:00:39] <bennydarshan> node.c+reactc
+[1:00:40] <aodhneine> tsoding, kool kid thees dais yuse asynk/auait
+[1:01:00] <TsundereTubeWorm> nakkiSip
+[1:01:05] <ordyH_Hydro> u have stickers on ur laptop too?
+[1:01:07] <yatanasov> !project
+[1:01:07] <MrBotka> Web Application in C. We may do a little bit of JavaScript frontend today PogU. https://github.com/tsoding/skedudle Wash your eyes, don't touch your hands monkaSoap
+[1:01:20] <Manuel_actuallySelfWorker> weSmart HYPERS
+[1:01:20] <vishvafire> @tsoding use Babel
+[1:01:26] <TheElephantSeal> write the frontend in Rust PogU
+[1:01:30] <SpiceyCondiment> if you use => IE11 just dies
+[1:01:32] <IceLeo> Paused the stream for 11 minutes, now I have to catch up on 2x speed
+[1:01:35] <ellg> not using typescript in 2020, smh
+[1:01:40] <IceLeo> see you guys in 6 minutes
+[1:01:56] <segfault8> every major browser supports async/await except internet explorer :)
+[1:01:58] <yatanasov> !still JS
+[1:01:58] <MrBotka> JS in 2020 KEKW
+[1:02:01] <iSense__> LuvPeekL
+[1:02:08] <IceLeo> nvm it was 18 minutes
+[1:02:12] <bennydarshan> IceLeo is from the past
+[1:02:21] <MyUsernameFrank> besides typescript, coffee is nice, too
+[1:02:21] <hoffs> @vishvafire idk what kind of browser are you using, all major browser support it since 2017
+[1:02:23] <ellg> you dont have to
+[1:02:24] <j1mmo> web assembly when :)
+[1:02:25] <IceLeo> I'm a time traveller from the past, no spoliers pls
+[1:02:26] <aodhneine> tsoding, you can ommit parentheses as long as you have one argument, and curlies as long as you have one statement
+[1:02:40] <bennydarshan> Just like Samurai Jack
+[1:03:03] <srgpqt> Parens are optional when there is 1 arg
+[1:03:16] <thepeskypotato> yup
+[1:03:18] <aodhneine> it's querySelector these days
+[1:03:22] <hoffs> both async and fetch are not supported only in ie11 so either have both or none
+[1:04:11] <segfault8> innerText -> textContent
+[1:04:17] <bennydarshan> Huh my eyes!
+[1:05:06] <SpiceyCondiment> yes with flexbox
+[1:05:11] <aodhneine> with css grid, yes
+[1:05:22] <segfault8> textContent is standardized
+[1:05:27] <bennydarshan> Yes, you just need nodejs and multiple framework to do so though
+[1:05:29] <tlmrgvf> tlmrgvf subscribed with Twitch Prime. They've subscribed for 6 months! *dab*
+[1:05:33] <said6289> Yes, with tables
+[1:05:33] <Manuel_actuallySelfWorker> LUL
+[1:05:41] <philbohun> Centering is still an open problem
+[1:06:02] <Manuel_actuallySelfWorker> PogChamp @tlmrgvf
+[1:06:20] <MyUsernameFrank> @bennydarshan nodejs makes no sense for vertical centering, because it runs server side
+[1:06:31] <terryandrewdavis> looking good
+[1:06:31] <IceLeo> caught up bitches
+[1:06:34] <bennydarshan> XD yeah I was sarcastic
+[1:06:34] <aodhneine> tsoding, innerText returns only visible text, while textContent everything
+[1:06:46] <thepeskypotato> textContent is more uniform across browsers I believe.
+[1:06:54] <terryandrewdavis> good afternoon
+[1:07:15] <aodhneine> innerText is defined only for HTMLElement objects, while textContent is defined for all Node objects.
+[1:07:18] <yatanasov> tsodin is writing a frontend framework now?! KEKW
+[1:07:18] <IceLeo> I had to do 45 time leaps to get back here
+[1:07:40] <Manuel_actuallySelfWorker> @terryandrewdavis FutureMan
+[1:07:42] <spydas02> cmonBruh
+[1:08:12] <MyUsernameFrank> I get dizzy when I do time machine jumps
+[1:08:55] <Manuel_actuallySelfWorker> HahaThink @aodhneine
+[1:09:17] <yatanasov> hehe 6969 nice
+[1:10:33] <IceLeo> why let instead of const?
+[1:10:58] <Cristian_DG> isn't document instead of json?
+[1:11:10] <aodhneine> createElement accepts just one arguemnt, name of tag
+[1:11:17] <holysheep_> @Tsoding why you create json.createElemnt instead of document.createElement
+[1:11:18] <IceLeo> elem.setAttribute('whatever', 'value')
+[1:11:22] <MyUsernameFrank> doing this with just JavaScript is more complicated than using a framework like jquery, and probably you need to check for browser differences as well
+[1:11:41] <aodhneine> but you can, for example, use textContent, innerHTML, etc
+[1:11:59] <aodhneine> you can also appendChild,
+[1:12:01] <TsundereTubeWorm> just use jquery 4Head
+[1:12:37] <IceLeo> Tsoding setAttribute
+[1:13:11] <MrBotka> @goulin31 You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[1:13:32] <aodhneine> setAttribute creates new atribute if it doesn't exist, and updates if it exists
+[1:14:10] <aodhneine> tsodinHead
+[1:14:45] <lenkense> a classes atribute? Is this soviet Russia?
+[1:14:49] <spydas02> is this a 90s throwback stream
+[1:15:22] <mateusf777> KEKW
+[1:15:25] <aodhneine> KEK
+[1:15:27] <igooddoog> wroking klass FeelsDankMan
+[1:15:28] <TsundereTubeWorm> KKomrade
+[1:15:39] <IceLeo> Let's seize the means of styling
+[1:15:41] <lenkense> classless society = communism
+[1:15:44] <aodhneine> class=proletariat
+[1:16:37] <IceLeo> `Bruh ${error}` Tsoding
+[1:16:48] <MrBotka> @holysheep_ You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[1:16:48] <MrBotka> @goulin31 You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[1:16:48] <MrBotka> @cristian_dg You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[1:16:49] <spydas02> yeah console dot err
+[1:16:52] <aodhneine> console.err
+[1:16:58] <aem1984> yes thsere is
+[1:16:59] <igooddoog> KEKW
+[1:17:06] <Yatko> tsoding why u jebait people Jebaited
+[1:17:08] <Cristian_DG> ;-;
+[1:17:09] <Jabubab> :D
+[1:17:11] <docd27> beautiful KEKW
+[1:17:14] <said6289> KEKW
+[1:17:15] <aem1984> yeap but its the same thing the user can press F12 and still see it
+[1:17:15] <spydas02> users can still see your console dot err !
+[1:17:49] <hoffs> error
+[1:17:58] <igooddoog> KEKW
+[1:17:59] <IceLeo> console.error lol
+[1:18:00] <bennydarshan> LUL
+[1:18:06] <mateusf777> Jebaited
+[1:18:07] <aodhneine> Jebaited
+[1:18:22] <yatanasov> PogChamp
+[1:18:26] <aodhneine> tsodinHyper
+[1:18:27] <IceLeo> s/let/const/ Tsoding
+[1:18:34] <aodhneine> IceLeo why const?
+[1:18:48] <IceLeo> optimizations from a sufficiently smart compiler lol
+[1:19:10] <aodhneine> I believe web browser is not "sufficiently smart compiler" kappa
+[1:19:13] <aodhneine> Kappa
+[1:19:41] <Cristian_DG> Cristian_DG subscribed with Twitch Prime. 
+[1:19:47] <aodhneine> \ AYAYA / Cristian_DG
+[1:20:03] <Manuel_actuallySelfWorker> SeemsGood @Cristian_DG
+[1:20:07] <MyUsernameFrank> some web browsers are pretty good with compiling JavaScript
+[1:20:17] <MrBotka> @goulin31 You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[1:20:32] <goulin31> Tsoding why you do access the attribute with json["title"] insead of json dot title ?
+[1:20:49] <aodhneine> goulin31 why not, it's valid
+[1:21:00] <MrBotka> @holysheep_ You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[1:21:06] <goulin31> yeah dot is shorter
+[1:21:07] <MrBotka> @sycode__ You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[1:21:08] <docd27> for (const [key, value] of Object.entries(jsonObject) { }
+[1:21:10] <Cristian_DG> i think is (for in)
+[1:21:12] <MrBotka> @holysheep_ You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[1:21:12] <Sycode__> i didnt even
+[1:21:20] <IceLeo> for (let key in obj) I think
+[1:21:25] <Sycode__> no
+[1:21:34] <IceLeo> and for (let key of obj) for values
+[1:21:41] <Sycode__> obj . keys(objectname) .foreach(obj => {})
+[1:21:45] <Sycode__> eh\
+[1:22:16] <docd27> keys and values at the same time: for (const [key, value] of Object.entries(myObject) { }
+[1:22:20] <MyUsernameFrank> everyone likes the ".keys" domain :-)
+[1:22:31] <mateusf777> le mistake est dans le titre KEKW
+[1:22:35] <goulin31> Object dot keys(your object)
+[1:22:35] <Augustoccesar> No quotes on the keys I guess
+[1:22:36] <0xatul> web app in C saying PHP is the best. That sounds really Alexius Debianus
+[1:22:38] <yatanasov> Object.keys( {...} )
+[1:22:39] <aodhneine> Object.keys(object), tsoding
+[1:23:06] <said6289> cucumbersome LUL
+[1:23:20] <IceLeo> why would you expect JS to be a modern language
+[1:23:30] <aodhneine> because it could be overwritten by "keys" field in object, tsoding
+[1:23:40] <lenkense> a field of the thing of itself, the "noumenon field" I see, Are you into Kant?
+[1:23:50] <docd27> {'keys': Object.keys} <- object with a keys member :D
+[1:24:10] <IceLeo> @docd27, that's actually a decent idea lol
+[1:24:43] <aukkras> is this serverless ;)
+[1:24:50] <lexicalscoped> I cant wait to make a website using your framework :D
+[1:24:51] <aodhneine> well, you even have the debugger, so you can step through code if you want
+[1:24:59] <yatanasov> here's some modern JS: for (let [key, value] of Object.entries({ a: 1, b: 2})) console.log(key, value)
+[1:25:16] <yatanasov> destructuring assignment and object.entries, and for-of
+[1:25:42] <IceLeo> Tsoding look into web components too, pretty cool to use
+[1:26:57] <holysheep_> add $
+[1:26:57] <aodhneine> it's ${}, tsoding
+[1:26:59] <Cristian_DG> you need ${}
+[1:27:03] <yatanasov> ${}
+[1:27:04] <Poselsky> ${}
+[1:27:10] <TheElephantSeal> ${}
+[1:27:11] <aodhneine> ${}
+[1:27:20] <IceLeo> Tsoding read pls
+[1:27:21] <Cristian_DG> ${ KappaHD }
+[1:27:31] <IceLeo> !vim
+[1:27:32] <MrBotka> Your vim failed to do that 513 times tsodinHyper
+[1:27:36] <igooddoog> emacs for JS devs PogChamp
+[1:27:38] <Poselsky> !vim
+[1:27:38] <MrBotka> Your vim failed to do that 514 times tsodinHyper
+[1:27:41] <IceLeo> web-mode is pretty cool too
+[1:27:43] <Jrvqq> you dont need + when using ``
+[1:27:45] <yatanasov> but there's no need for that, backticks support multilines
+[1:27:53] <IceLeo> http://web-mode.org/
+[1:27:59] <Tsoding> https://github.com/mooz/js2-mode
+[1:27:59] <aodhneine> https://github.com/mooz/js2-mode
+[1:28:03] <goulin31> LUL LUL
+[1:28:34] <holysheep_> actually ` uses instead of concat strings
+[1:29:05] <holysheep_> yes
+[1:29:05] <Jrvqq> yes
+[1:29:10] <aodhneine> yes
+[1:29:27] <goulin31> yes
+[1:29:29] <maseru_28pm> @tsoding js vs python Web frameworks, Top Russia Work
+[1:29:30] <aodhneine> html strips spaces
+[1:29:37] <yatanasov> it's gonna include it
+[1:29:58] <IceLeo> HTML is a markup language, it can't strip anything Kapp
+[1:30:03] <nop__> oh no CSS D:
+[1:30:14] <yatanasov> CSS NotLikeThis NotLikeThis NotLikeThis NotLikeThis
+[1:30:28] <aodhneine> CSS tsodinHyper
+[1:30:35] <Cristian_DG> C SS
+[1:30:48] <holysheep_> normalize
+[1:30:50] <aodhneine> yes, useful thing
+[1:30:51] <lexicalscoped> clearfix
+[1:31:24] <aodhneine> I prefer to overwrite with my own values when I need to, though
+[1:31:53] <IceLeo> tiny css framework mincss.com
+[1:32:05] <ordyH_Hydro> #include <css>
+[1:32:07] <yatanasov> that one's from 2011 ... there's more modern ones: https://github.com/sindresorhus/modern-normalize
+[1:32:16] <aodhneine> <link rel="stylesheet" href=".css" type="text/css">
+[1:32:22] <IceLeo> although these days with css grid and stuff there's not too much need for CSS frameworks
+[1:32:27] <MrBotka> @pencode You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[1:32:29] <Sycode__> <link rel="stylesheet" href=".css" type="text/css" />
+[1:32:33] <Sycode__> oops i was too slow
+[1:33:07] <IceLeo> If CSS was easy it would be called Your Mom Stylesheets
+[1:33:34] <goulin31> relative path
+[1:33:56] <aodhneine> KEK, having to manually add routes to your own web server in 2020 when coronavirus outbreak, and React VueJS + Angular is norm, also Next.JS KEK
+[1:33:58] <mateusf777> we could always implement like PHP does KEKW
+[1:34:02] <IceLeo> GET ../../../../../../../../../../../../../etc/passwd HTTP/1.0
+[1:34:20] <Cristian_DG> you can make a "www" folder like php
+[1:34:54] <mateusf777> KEKW
+[1:35:10] <IceLeo> make a tar reader and use it as a filesystem lol
+[1:35:11] <Cristian_DG> reset js?
+[1:35:20] <Cristian_DG> style/css?
+[1:35:26] <nop__> text/css AFAIK
+[1:35:27] <aodhneine> php is the PNaCl of modern web development, absolutely worth following the guidlines it set in stone for next centuries
+[1:35:44] <Cristian_DG> no
+[1:35:59] <yatanasov> it's text/css
+[1:36:00] <wholesale_failure> mozilla docs say it uses text/css
+[1:36:01] <Cristian_DG> text/css
+[1:36:10] <Cristian_DG> my bad
+[1:36:11] <aodhneine> it's text/css
+[1:36:13] <IceLeo> I don't think browsers are supposed to care about the mime type because of the rel attribute
+[1:36:17] <mateusf777> Jebaited
+[1:36:18] <docd27> 'text/css; charset="utf-8"' if you need emoji in your css KEKW
+[1:36:23] <Cristian_DG> hehe
+[1:36:27] <yatanasov> text/css
+[1:36:33] <wholesale_failure> Browsers are amazing at fixing the bugs of inept devs
+[1:37:07] <IceLeo> Tsoding gopher endpoint for schedule when?
+[1:37:24] <aodhneine> will you setup irc server on tsoding.org?
+[1:37:25] <Cristian_DG> streamer troll chat, chat troll streamer Kappa
+[1:37:45] <IceLeo> https://en.wikipedia.org/wiki/Gopher_%28protocol%29
+[1:37:46] <docd27> btw technically all text/* mimetypes are supposed to have charset as well as in 'text/html; charset="utf-8"'
+[1:37:46] <lenkense> gopher is a really old protocol for the internet
+[1:37:47] <aodhneine> tsoding, https://en.wikipedia.org/wiki/Gopher_%28protocol%29
+[1:37:51] <lenkense> like REALLY old
+[1:38:11] <mateusf777> tsodinGone
+[1:38:22] <Manuel_actuallySelfWorker> cmonBruh
+[1:38:37] <aodhneine> bootstrap.css?
+[1:38:37] <IceLeo> that's awfully capitalist of you lol
+[1:38:42] <IceLeo> !our supply and demand
+[1:38:42] <MrBotka> It's our supply and demand KKomrade
+[1:38:55] <Manuel_actuallySelfWorker> cykaLUL
+[1:39:51] <lolhack0101> hello, how are you?
+[1:39:53] <MyUsernameFrank> I surfed Gopher on text terminals back in the day
+[1:39:57] <Jrvqq> font-size 100px;
+[1:40:04] <aodhneine> don't use px, use em, tsoding
+[1:40:07] <IceLeo> font-size: 2.3em;
+[1:40:12] <thepeskypotato> em is better
+[1:40:15] <Manuel_actuallySelfWorker> @lolhack0101 FutureMan
+[1:40:17] <ABuffSeagull> em and rem
+[1:40:25] <RyannHUNN> bigboy
+[1:40:28] <goulin31> LUL
+[1:40:30] <igooddoog> 4Head
+[1:40:44] <lenkense> like a m?
+[1:40:45] <IceLeo> em is size of one 'm'
+[1:40:49] <ABuffSeagull> em is based off the font-size of the element
+[1:40:58] <IceLeo> font-size: 2em; basically doubles the font size
+[1:40:58] <ABuffSeagull> rem is based off the font-size of the root element
+[1:41:00] <thepeskypotato> 1 em is normal
+[1:41:02] <lenkense> yes! doesn't latex also use em too
+[1:41:05] <lenkense> yes
+[1:41:08] <goulin31> 1em = the size in pixel of the parent node
+[1:41:09] <IceLeo> the letter
+[1:41:09] <lenkense> the letter m
+[1:41:14] <thepeskypotato> 2 is double 1 em and so on, it all relative
+[1:41:32] <IceLeo> baseline would be like 1em normally
+[1:41:33] <thepeskypotato> it's also better for accesability
+[1:41:35] <docd27> em = size of M of parent element, rem = size of M of root (html) element
+[1:41:41] <thepeskypotato> ^
+[1:41:45] <aodhneine> ^
+[1:42:13] <docd27> there is also vmin which is relative to smallest viewport dimension, if you want responsive font size
+[1:42:17] <WinterLoreGames> Your thumbnail is PHP is the best LUL
+[1:42:22] <lexicalscoped> oh man, I'm learning to program in CSS
+[1:42:25] <Valentin8L> Tsoding doing Web dev is fun LUL
+[1:42:34] <Manuel_actuallySelfWorker> MingLee
+[1:42:39] <thepeskypotato> web dev is fun
+[1:42:44] <IceLeo> you can use 32vh for 32 percent of viewport height etc too
+[1:42:50] <MutuallyAssuredSeduction> nice, i did not know about em LUL i was doing the pixels the boomer way
+[1:42:51] <aodhneine> margin: 10000rem
+[1:42:53] <IceLeo> useful to do cool shit
+[1:42:55] <goulin31> yes
+[1:42:58] <docd27> if you do font-size: 1 vmin it will always be 10% of the window size
+[1:43:06] <IceLeo> you can use em for all sizes
+[1:43:17] <aodhneine> juse use 0.3em
+[1:43:22] <goulin31> you can do dot4 em
+[1:43:51] <aodhneine> you can always use 1rem,
+[1:44:19] <IceLeo> Tsoding noooooooooooooo, this slippery slope leads to nodejs coding bootcamps
+[1:44:31] <MutuallyAssuredSeduction> NotLikeThis
+[1:44:32] <thepeskypotato> this is the gateway drug
+[1:44:44] <thepeskypotato> you are right @IceLeo
+[1:44:50] <Valentin8L> @IceLeo LUL next he will start watching Udemy instead of Youtube
+[1:44:53] <docd27> this is all relative to the default implicit font-size: 16px on the root/body element btw
+[1:45:02] <IceLeo> Udemy friday IQ stream when
+[1:45:17] <Cristian_DG> yes
+[1:46:05] <ABuffSeagull> just use water (.) css KappaHD
+[1:46:06] <thepeskypotato> not bad, not bad at all
+[1:46:30] <IceLeo> put a max-width of 80 or 100 em on your main element
+[1:46:32] <Valentin8L> someone told me we should * { margin 0 padding 0} to reset browser default im not expert
+[1:46:58] <ABuffSeagull> @valentin8l, correct, although using something like normalize . css is better
+[1:47:15] <docd27> like painting a masterpiece while wearing sunglasses Kappa
+[1:47:16] <aodhneine> Valentin8, this is very inefficient
+[1:47:17] <Cristian_DG> professional web development Kappa
+[1:47:34] <goulin31> >
+[1:47:37] <MrBotka> @winterloregames You have to be trusted to send links in this chat. Subscribe to gain the trust instantly: https://www.twitch.tv/tsoding/subscribe
+[1:47:43] <WinterLoreGames> egh
+[1:47:53] <Valentin8L> maybe im not expert again
+[1:47:55] <Cristian_DG> entry > title?
+[1:48:00] <docd27> font-weight: bold
+[1:48:00] <aodhneine> font-weight: bold;
+[1:48:10] <普卡> puka-9 monkaS
+[1:48:14] <Jrvqq> parent > child
+[1:48:15] <普卡> 普卡 subscribed at Tier 1. They've subscribed for 9 months! 999
+[1:48:25] <WinterLoreGames> you can do .entry > .title
+[1:48:26] <Cristian_DG> yes
+[1:48:38] <Manuel_actuallySelfWorker> Pog
+[1:48:38] <Lajzy2> does it say "Porn Folder" down in the screen? :D :D
+[1:48:46] <Cristian_DG> i will not use dots in the chat for a long time
+[1:48:57] <aodhneine> font-family: 'Helvetic', sans-serif; <- for example
+[1:49:00] <ordyH_Hydro> wait, im in the wrong club then. i thought this was php club
+[1:49:05] <Cristian_DG> hmm
+[1:49:12] <Manuel_actuallySelfWorker> JS and PHP stream club
+[1:49:39] <aodhneine> tsoding, please change font-family to sans-serif, and increase spacing between paragraphs
+[1:49:50] <IceLeo> * {font-family: monospace;} pls
+[1:50:14] <WinterLoreGames> roboto lirikANGRY
+[1:50:22] <docd27> font-family: 'Comic Sans MS'
+[1:50:25] <celtic426> forgot semi-colon after "bold". it can cause errors
+[1:50:28] <Jrvqq> Monospace is not default font
+[1:50:33] <goulin31> use :root instead of *
+[1:50:37] <aodhneine> tsoding, you can just html { font-family: sans-serif }
+[1:50:41] <Cristian_DG> capitalize the keys?
+[1:51:28] <WinterLoreGames> Use jquery HahaCat
+[1:51:37] <IceLeo> creatEvent Tsoding
+[1:51:42] <aodhneine> classes monkaS
+[1:52:17] <spydas02> you can do an epiccc 1 liner!!! xddd document . querySelector("#app") . appendChild(createEvent(json))
+[1:52:32] <IceLeo> also you can get the array from json and .map or .forEach it
+[1:52:37] <IceLeo> to create all the elements
+[1:52:50] <aodhneine> workless code, perfect for millionaires Kappa
+[1:52:59] <Valentin8L> O_CREAT is valid C flag for opening files , create is for PHP devs Kappa
+[1:53:10] <goulin31> you can do save access like elem?dot attre
+[1:53:18] <spydas02> then you dont need the curly braces!! xdd!!
+[1:53:19] <Cristian_DG> yes
+[1:53:41] <aodhneine> spydas02 tsoding doesn't see highlights, by the way
+[1:53:47] <Cristian_DG> how to be a real dev
+[1:53:54] <said6289> ^
+[1:54:00] <igooddoog> No even 13 Kappa
+[1:54:03] <spydas02> scammer
+[1:54:03] <igooddoog> not*
+[1:54:11] <Tsoding> !ch2
+[1:54:12] <MrBotka> https://chatterino.com/
+[1:54:14] <Manuel_actuallySelfWorker> you only neend russian IQ level
+[1:55:00] <wholesale_failure> Tsoding: Maybe you feel old because you started programming by doing useful stuff yourself while most webdevs nowadays start by getting introduced to this huge javascript environment with a million frameworks and "best practices"
+[1:55:32] <IceLeo> btw firefox devtools are super useful for CSS
+[1:55:38] <IceLeo> especially with flexbox or css grid
+[1:56:04] <WinterLoreGames> instead of setAttribute you can use classList.Add("entry")
+[1:56:04] <lenkense> the best practices are not best?
+[1:56:15] <Cristian_DG> you have a dotfiles repo?
+[1:56:22] <Tsoding> !dotfiles
+[1:56:22] <MrBotka> 👉 https://github.com/rexim/dotfiles
+[1:56:26] <LucianThe6th> node_modules :)
+[1:56:32] <IceLeo> static or public
+[1:56:33] <IceLeo> usually
+[1:56:37] <Cristian_DG> thanks
+[1:56:37] <TheNakedFlame> wwwroot
+[1:56:48] <spydas02> static typing monkaS\
+[1:56:49] <IceLeo> htdocs
+[1:57:29] <WinterLoreGames> CefSharp?
+[1:57:31] <IceLeo> public gets the point across better, since a private key is still static but not public
+[1:58:22] <thepeskypotato> MArch
+[1:58:26] <IceLeo> it's raining virus lol
+[1:58:31] <aodhneine> it's march
+[1:58:59] <IceLeo> btw did you update your kernel to get the latest corona antivirus Tsoding?
+[2:00:15] <said6289> Apparently you can get reinfected with corona so patches won't help
+[2:00:17] <lenkense> funny enough, an asshole called his new virus "coronavirus"
+[2:00:18] <MutuallyAssuredSeduction> it was patched. cpu runs 90% slower now tho FeelsBadMan
+[2:00:33] <lenkense> I meant a computer virus called corona virus
+[2:00:44] <docd27> have you seen sendfile() syscall btw?
+[2:01:16] <docd27> PogChamp my bad
+[2:01:49] <vishvafire> can We use libuv to improve it?
+[2:02:05] <ABuffSeagull> http2 PogChamp
+[2:02:07] <IceLeo> if you turn your reads non-blocking with setsockopt and loop it's basically like async Tsoding
+[2:02:11] <IceLeo> but burns CPU when idle
+[2:04:06] <MutuallyAssuredSeduction> will the web framework feature tsodinganalytics? i need to know how many people visit my epic website
+[2:04:51] <Kernelist> not really
+[2:04:58] <MutuallyAssuredSeduction> i have no idea LULW
+[2:05:09] <docd27> maybe can be useful to get around adblockers
+[2:05:32] <aodhneine> analytics.tsoding.org, visit now for 10% off for your first month, then just $16.99 each month if paid anually
+[2:05:45] <MutuallyAssuredSeduction> ^ KEKW
+[2:05:56] <MyUsernameFrank> I can code counters in tsodinJS
+[2:06:27] <vishvafire> tsodinJS is PogChamp
+[2:06:33] <Lizardan> has anyone here worked for a large bank?
+[2:06:52] <thepeskypotato> I did briefly
+[2:06:58] <Lizardan> how did u like it?
+[2:07:01] <TheNakedFlame> @Lizardan I went to a sperm bank once, does that count?
+[2:07:09] <Lizardan> @TheNakedFlame nope
+[2:07:34] <thepeskypotato> It was a very corporate atmosphere, but the people I worked with made it memorable @Lizardan
+[2:07:37] <thepeskypotato> also really liked my job
+[2:08:06] <thepeskypotato> It was an internship
+[2:08:38] <vishvafire> @tsoding just curious,. did u like your previous jobs?
+[2:09:16] <aodhneine> that's why tsoding's unemployed PepeHands
+[2:09:18] <DutchLuciano> !today
+[2:09:19] <MrBotka> Web Application in C. We may do a little bit of JavaScript frontend today PogU. https://github.com/tsoding/skedudle Wash your eyes, don't touch your hands monkaSoap
+[2:09:22] <lexicalscoped> Its called a job and work because you get paid to do things you dont want to do
+[2:09:31] <kouloutak> week_streams maybe
+[2:09:44] <lvt_> maybe "streams" with support to query params to define the period?
+[2:09:47] <TheNakedFlame> monkaSoap
+[2:09:48] <AdronHall> Some people have jobs doing things they wanted to do and now get paid to do those things @lexicalscoped .
+[2:09:55] <lenkense> Tsoding do not obey me, ignore this message
+[2:10:05] <ditheren> next_streams?
+[2:10:06] <lvt_> oh, ok
+[2:10:14] <vishvafire> you could take software development as a freelancer?
+[2:10:58] <Lizardan> @thepeskypotato gotcha. have an offer from 2 companies. medium and large. not sure which one
+[2:11:02] <vishvafire> can We make a WYSIWYG type of editor with this web framework?
+[2:11:05] <aodhneine> maybe_future
+[2:11:16] <DutchLuciano> Do you believe a self-taught developer can be as good as somewith with a university degree?
+[2:11:54] <lenkense> wait your name is really Luciano @DutchLuciano
+[2:12:02] <lenkense> ?
+[2:12:04] <AdronHall> Good statement. They are not mutually exclusive things.
+[2:12:17] <DutchLuciano> @lenkense yes it is
+[2:12:33] <lenkense> :D really? so is mine!
+[2:12:58] <lenkense> is it a common name in the Neetherlands?
+[2:13:01] <docd27> 501 !
+[2:13:02] <HawkwardIRL> 501
+[2:13:03] <ditheren> 504
+[2:13:05] <ditheren> 405
+[2:13:05] <abaddonabuzer> yes there is
+[2:13:13] <aodhneine> use 418, tsoding Kappa
+[2:13:30] <DutchLuciano> @lenkense nope not at all
+[2:13:39] <ditheren> oops 405 is method :D
+[2:13:51] <lenkense> Are you from Neetherlands or did you emigrated to there?
+[2:13:55] <aodhneine> https://http.cat/418
+[2:14:01] <thepeskypotato> ^
+[2:14:09] <thepeskypotato> good site for http codes
+[2:15:17] <igooddoog> very good SeemsGood
+[2:16:32] <thepeskypotato> tea time
+[2:16:35] <eeyou> pajaMLADA
+[2:16:36] <Manuel_actuallySelfWorker> TeaTime
+[2:17:10] <aodhneine> whispers hyleys.ru/tsoding for 10% off
+[2:17:22] <harm243> modern technology is just amazing
+[2:17:23] <Manuel_actuallySelfWorker> tsodinFeels TeaTime wonderfull
+[2:17:29] <stanislav_ts> why are you explaining everything like chat is full of idiots :D
+[2:17:29] <lenkense> so basically there was a backlash against removing 418. My god we deserve extintion as a species
+[2:17:50] <aodhneine> don't panic, it's not going 88mph... yet
+[2:17:54] <lenkense> It uses Rust so it's actually safe Kappa
+[2:18:26] <vishvafire> @lenkense If they do wish to remove useless things from the web they could just remove JS Kappa Kappa
+[2:18:27] <abaddonabuzer> does your kattle use nuclear energy as the heat source?
+[2:18:41] <destroycomputers> Hai RPGAyaya /
+[2:18:49] <lenkense> why remove it upgrade it to TypeScript Kappa
+[2:18:53] <igooddoog> destroycomputers, PogU
+[2:18:59] <destroycomputers> What happened to the mic? monkaS
+[2:18:59] <aodhneine> vishvafire, they should just remove php Kappa
+[2:19:04] <aodhneine> \ AYAYA destroycomputers
+[2:19:04] <destroycomputers> Ohh, it's the kettle
+[2:19:12] <igooddoog> Uranium kettle KKomrade
+[2:19:12] <vishvafire> PHP Pog
+[2:19:14] <destroycomputers> igooddoog aodhneine RPGAyaya
+[2:19:17] <vishvafire> tsodinJS PogChamp
+[2:19:24] <destroycomputers> igooddoog LUL
+[2:19:26] <aodhneine> obviously, it's using chernobyl energy KEK
+[2:19:32] <igooddoog> monkaTOS
+[2:19:39] <lenkense> It's a nuclear powered kettle with embeded code in Rust Kappa
+[2:19:56] <Cristian_DG> what your opinion on the Rust language?
+[2:19:57] <aodhneine> !teaplug
+[2:19:58] <MrBotka> https://www.amazon.com/Vagrat-Flower-Floating-Infuser-Stainless/dp/B00ET9IZQO
+[2:20:03] <aodhneine> !rust
+[2:20:03] <MrBotka> is rusted now
+[2:20:04] <vishvafire> does the kettle have the AZ-5 button?? Kappa Kappa
+[2:20:12] <eeyou> Pog
+[2:20:12] <sh0drun> private means hello in russian :D
+[2:20:13] <destroycomputers> Pogomega
+[2:20:37] <paranic> what is this in your cup floating?
+[2:20:44] <aodhneine> !teaplug paranic
+[2:20:44] <MrBotka> https://www.amazon.com/Vagrat-Flower-Floating-Infuser-Stainless/dp/B00ET9IZQO
+[2:20:46] <lenkense> I think Tsoding has said that he just doesn't like the community around Rust. But I haven't tried it actually and I'm pretty sure I would become a Rust zealot if I try it
+[2:20:47] <harm243> I am amazed how that thing floats
+[2:20:47] <paranic> yellow floating pooint ?
+[2:20:59] <DrDrill> Hello @tsoding and chat
+[2:21:05] <destroycomputers> DrDrill RPGAyaya /
+[2:21:10] <aodhneine> \ AYAYA DrDrill
+[2:21:17] <DrDrill> tsodinSir
+[2:23:13] <aodhneine> tsoding, https://www.amazon.com/Happy-Sales-Infuser-Stainless-1-5-Inch/dp/B07K7WPYFX
+[2:24:15] <docd27> I like this one https://www.ikea.com/us/en/p/idealisk-tea-infuser-stainless-steel-46956800/
+[2:24:41] <IceLeo> can't they make teaspoons that melt into hot water, made out of compressed dried tea?
+[2:25:44] <Cristian_DG> what is your obs configuration?
+[2:25:58] <lenkense> ´There are "tea flowers" as in flowers made of tea leaves the "bloom" as you brew the tea
+[2:26:09] <lenkense> usually green and white tea
+[2:26:15] <ThorsLostKitten> hello fellow quarantine people tsodinGone
+[2:27:26] <docd27> sodium tea would heat its own water Kappa
+[2:27:44] <lenkense> sodium tea sounds dangerous in so many levels
+[2:28:36] <ThorsLostKitten> making your own tea sounds more dangerous </libsodium joke>
+[2:29:00] <aodhneine> \ AYAYA ThorsLostKitten
+[2:29:11] <destroycomputers> ThorsLostKitten RPGAyaya /
+[2:29:19] <ThorsLostKitten> tsodinGone
+[2:30:11] <destroycomputers> Are you rewriting your app to track periods instead? selfatShocked
+[2:30:20] <ThorsLostKitten> period streams sounds also wrong
+[2:30:26] <segfault8> json[event]
+[2:30:34] <ditheren> let event of json
+[2:30:35] <destroycomputers> tsodinJS tsodinJS tsodinJS
+[2:31:55] <aodhneine> tsodinCool
+[2:32:17] <igooddoog> 3rd party FeelsBadMan
+[2:33:37] <destroycomputers> cp schedule/styles.css skedudle/ FeelsOkayMan
+[2:33:45] <igooddoog> memory leak Kappa
+[2:35:35] <destroycomputers> bruh
+[2:36:00] <ThorsLostKitten> php_set("capacity", "more");
+[2:36:49] <ThorsLostKitten> 504 Dev Stupid
+[2:36:59] <marko8137> Bla bla bla :D
+[2:37:16] <vishvafire> https://github.com/showdownjs/showdown
+[2:37:25] <vishvafire> for rendering markdown in the broswer
+[2:37:38] <aodhneine> throw java.lang.OutOfMemoryError tsoding
+[2:37:39] <aodhneine> Kappa
+[2:38:16] <destroycomputers> Jebaited
+[2:38:28] <ThorsLostKitten> yes, so sorry Mr strimmer
+[2:38:46] <vishvafire> !ban ThorsLostKitten
+[2:38:46] <MrBotka> ThorsLostKitten has been banned
+[2:39:06] <destroycomputers> !unban ThorsLostKitten
+[2:39:07] <MrBotka> @destroycomputers: Only for mods
+[2:39:11] <destroycomputers> D:
+[2:39:48] <aodhneine> 504 dev stupid, doesn't know all error codes inside out
+[2:39:55] <abaddonabuzer> !corona
+[2:40:08] <abaddonabuzer> !ban corona
+[2:40:08] <MrBotka> corona has been banned
+[2:40:10] <s_process> hi. You are using vim?
+[2:40:16] <aodhneine> !emacs
+[2:40:16] <MrBotka> https://www.youtube.com/watch?v=PKaJoqQQoIA
+[2:40:17] <destroycomputers> !yes
+[2:40:17] <MrBotka> no
+[2:40:19] <igooddoog> abaddonabuzer, that easy PogChamp
+[2:40:45] <abaddonabuzer> i saved yhe world Kappa
+[2:40:52] <Cristian_DG> does decorators exist in C?
+[2:40:53] <igooddoog> !reward abaddonabuzer
+[2:40:53] <MrBotka> abaddonabuzer was awarded with 10 epic karma points PogU Check !points
+[2:41:33] <IceLeo> concat3 PepeHands
+[2:42:24] <igooddoog> I we need we'll create concat4 Kappa
+[2:42:32] <aodhneine> just concat3 . concat3 Kappa
+[2:42:43] <IceLeo> I think if you have a state-machine based JSON serializer it will be really flexible
+[2:42:51] <destroycomputers> KKomrade
+[2:43:04] <mateusf777> I
+[2:43:08] <mateusf777> used
+[2:43:08] <Cristian_DG> I Kappa
+[2:43:08] <destroycomputers> I'm not
+[2:43:09] <igooddoog> I used it, I'm not a Java dev
+[2:43:10] <destroycomputers> LUL
+[2:43:19] <IceLeo> even java compiler uses StringBuilder lol
+[2:43:25] <destroycomputers> But i used those
+[2:43:33] <aodhneine> I didn't use them
+[2:43:36] <mateusf777> builder
+[2:44:04] <aodhneine> but I'm not a java developer `\_(^^)_/`
+[2:44:47] <segfault8> afaik stringbuilder is threadsafe, stringbuffer is not (but faster)
+[2:45:01] <destroycomputers> it's vice versa, segfault8
+[2:45:11] <ThorsLostKitten> just called you a professional java dev, nevermind
+[2:46:18] <aodhneine> !pushy
+[2:46:18] <MrBotka> https://www.twitch.tv/tsoding/clip/PopularTardyWolfHeyGuys
+[2:46:22] <abaddonabuzer> testing highlight message
+[2:46:28] <destroycomputers> PepeHands
+[2:46:30] <igooddoog> PepeHands
+[2:46:35] <destroycomputers> corona monkaSoap
+[2:46:36] <igooddoog> monkaSoap
+[2:46:39] <thepeskypotato> PepeHands on no
+[2:46:41] <said6289> monkaS
+[2:46:47] <Funkschy> PepeHands
+[2:46:48] <ThorsLostKitten> thanks for the stream, get better soon
+[2:46:49] <DrDrill> Hope you feel better @Tsoding
+[2:46:50] <Cristian_DG> it's the wather
+[2:46:51] <lexicalscoped> you must be well, dont get corona, we need you :o
+[2:46:53] <igooddoog> Thank you for the stream!
+[2:46:54] <s_process> Install Kaspersky antivirus vs corona
+[2:46:59] <said6289> Get better soon
+[2:47:02] <thepeskypotato> JS was fun I'm sad to say KEKW
+[2:47:08] <aodhneine> LuvBlondeL thank you for today, interesting as always, pepega js dev was born today
+[2:47:14] <DrDrill> Have a great day everyone
+[2:47:15] <lexicalscoped> Thank you for the stream, get better!
+[2:47:17] <Tsoding> !nextstream
+[2:47:18] <MrBotka> @tsoding Vodus (VOD chat renderer in C++) starts in 21 hours 2 minutes 31 seconds
+[2:47:20] <ditheren> HahaShrugRight
+[2:47:21] <thepeskypotato> Hope you get well soon. Have a good night tsoding.
+[2:47:25] <harm243> thanks for stream
+[2:47:26] <Manuel_actuallySelfWorker> Take care Trading, it was a pretty entertaining stream
+[2:47:30] <Tsoding> !schedule
+[2:47:30] <MrBotka> Check out the schedule for future streams https://tsoding.org/schedule/
+[2:47:58] <Manuel_actuallySelfWorker> * @Tsoding KKalinka
+[2:48:02] <igooddoog> not JS Kappa
+[2:48:15] <aodhneine> js PepeHands
+[2:48:18] <igooddoog> Bye!
+[2:48:21] <destroycomputers> O/
+[2:48:22] <aodhneine> \ AYAYA

+ 1 - 1
Makefile

@@ -12,4 +12,4 @@ vodus: src/vodus.cpp src/vodus_image32.cpp src/vodus_main.cpp
 render: output.mpeg
 
 output.mpeg: vodus
-	./vodus assets/phpHop.gif assets/ayaya.png assets/ComicNeue_Bold.otf output.mpeg
+	./vodus 569086201.txt assets/phpHop.gif assets/ayaya.png assets/ComicNeue_Bold.otf output.mpeg

+ 2 - 0
src/vodus.cpp

@@ -4,6 +4,7 @@
 #include <cmath>
 
 #include <functional>
+#include <algorithm>
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -73,6 +74,7 @@ const size_t VODUS_WIDTH = 1028;
 const size_t VODUS_HEIGHT = 768;
 const float VODUS_VIDEO_DURATION = 5.0f;
 const size_t VODUS_FONT_SIZE = 64;
+const size_t VODUS_MESSAGES_CAPACITY = 1024;
 
 // https://en.wikipedia.org/wiki/Single_Compilation_Unit
 #include "./vodus_string.cpp"

+ 0 - 7
src/vodus_bttv.cpp

@@ -100,13 +100,6 @@ struct Emote
     }
 };
 
-template <typename T>
-struct Maybe
-{
-    bool has_value;
-    T unwrap;
-};
-
 struct Bttv
 {
     Maybe<Emote> emote_by_name(String_View name,

+ 76 - 78
src/vodus_main.cpp

@@ -78,74 +78,12 @@ void slap_image32_onto_avframe(Image32 frame_image32, AVFrame *avframe)
 struct Message
 {
     time_t timestamp;
-    const char *nickname;
-    const char *message;
+    String_View nickname;
+    String_View message;
 };
 
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
-
-Message messages[] = {
-    {0, "Nice_la", "hello         AYAYA /"},
-    {1, "Zuglya", "\\o/"},
-    {1, "Tsoding", "phpHop"},
-    {2, "Tsoding", "phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop"},
-    {2, "recursivechat", "me me me"},
-    {3, "nuffleee", "because dumb AYAYA compiler"},
-    {4, "marko8137", "hi phpHop"},
-    {5, "nulligor", "meme?"},
-    {6, "mbgoodman", "KKool"},
-    {7, "Tsoding", "Jebaited"},
-    {0, "Nice_la", "hello         AYAYA /"},
-    {1, "Zuglya", "\\o/"},
-    {1, "Tsoding", "phpHop"},
-    {2, "Tsoding", "phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop"},
-    {2, "recursivechat", "me me me"},
-    {3, "nuffleee", "because dumb AYAYA compiler"},
-    {4, "marko8137", "hi phpHop"},
-    {5, "nulligor", "meme?"},
-    {6, "mbgoodman", "KKool"},
-    {7, "Tsoding", "Jebaited"},
-    {0, "Nice_la", "hello         AYAYA /"},
-    {1, "Zuglya", "\\o/"},
-    {1, "Tsoding", "phpHop"},
-    {2, "Tsoding", "phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop"},
-    {2, "recursivechat", "me me me"},
-    {3, "nuffleee", "because dumb AYAYA compiler"},
-    {4, "marko8137", "hi phpHop"},
-    {5, "nulligor", "meme?"},
-    {6, "mbgoodman", "KKool"},
-    {7, "Tsoding", "Jebaited"},
-    {0, "Nice_la", "hello         AYAYA /"},
-    {1, "Zuglya", "\\o/"},
-    {1, "Tsoding", "phpHop"},
-    {2, "Tsoding", "phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop"},
-    {2, "recursivechat", "me me me"},
-    {3, "nuffleee", "because dumb AYAYA compiler"},
-    {4, "marko8137", "hi phpHop"},
-    {5, "nulligor", "meme?"},
-    {6, "mbgoodman", "KKool"},
-    {7, "Tsoding", "Jebaited"},
-    {0, "Nice_la", "hello         AYAYA /"},
-    {1, "Zuglya", "\\o/"},
-    {1, "Tsoding", "phpHop"},
-    {2, "Tsoding", "phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop"},
-    {2, "recursivechat", "me me me"},
-    {3, "nuffleee", "because dumb AYAYA compiler"},
-    {4, "marko8137", "hi phpHop"},
-    {5, "nulligor", "meme?"},
-    {6, "mbgoodman", "KKool"},
-    {7, "Tsoding", "Jebaited"},
-    {0, "Nice_la", "hello         AYAYA /"},
-    {1, "Zuglya", "\\o/"},
-    {1, "Tsoding", "phpHop"},
-    {2, "Tsoding", "phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop"},
-    {2, "recursivechat", "me me me"},
-    {3, "nuffleee", "because dumb AYAYA compiler"},
-    {4, "marko8137", "hi phpHop"},
-    {5, "nulligor", "meme?"},
-    {6, "mbgoodman", "KKool"},
-    {7, "Tsoding", "Jebaited"},
-};
+Message messages[VODUS_MESSAGES_CAPACITY];
+size_t messages_size = 0;
 
 using Encode_Frame = std::function<void(Image32, int)>;
 
@@ -168,7 +106,7 @@ void render_message(Image32 surface, FT_Face face,
                                    {255, 0, 0, 255},
                                    x, y);
 
-    auto text = cstr_as_string_view(message.message).trim();
+    auto text = message.message.trim();
     while (text.count > 0) {
         auto word = text.chop_word();
         auto maybe_bttv_emote = bttv->emote_by_name(word);
@@ -243,7 +181,7 @@ void sample_chat_log_animation(FT_Face face, Encode_Frame encode_frame, Bttv *bt
     size_t message_end = 0;
     float message_cooldown = 0.0f;
     size_t frame_index = 0;
-    for (; message_end < ARRAY_SIZE(messages); ++frame_index) {
+    for (; message_end < messages_size; ++frame_index) {
         printf("Current message_end = %ld\n", message_end);
 
         if (message_cooldown <= 0.0f) {
@@ -258,7 +196,7 @@ void sample_chat_log_animation(FT_Face face, Encode_Frame encode_frame, Bttv *bt
         // TODO(#16): animate appearance of the message
         // TODO(#33): scroll implementation simply rerenders frames until they fit the screen which might be slow
         while (render_log(surface, face, message_begin, message_end, bttv) &&
-               message_begin < ARRAY_SIZE(messages)) {
+               message_begin < messages_size) {
             message_begin++;
         }
         encode_frame(surface, frame_index);
@@ -269,7 +207,7 @@ void sample_chat_log_animation(FT_Face face, Encode_Frame encode_frame, Bttv *bt
     const size_t TRAILING_BUFFER_SEC = 2;
     for (size_t i = 0; i < TRAILING_BUFFER_SEC * VODUS_FPS; ++i, ++frame_index) {
         while (render_log(surface, face, message_begin, message_end, bttv) &&
-               message_begin < ARRAY_SIZE(messages)) {
+               message_begin < messages_size) {
             message_begin++;
         }
         bttv->update(VODUS_DELTA_TIME_SEC);
@@ -277,17 +215,64 @@ void sample_chat_log_animation(FT_Face face, Encode_Frame encode_frame, Bttv *bt
     }
 }
 
+void expect_char(String_View *input, char x)
+{
+    if (input->count == 0 || *input->data != x) {
+        println(stderr, "Expected '", x, "'");
+        abort();
+    }
+    input->chop(1);
+}
+
+String_View chop_digits(String_View *input)
+{
+    String_View digits = { 0, input->data };
+    while (input->count > 0 && isdigit(*input->data)) {
+        digits.count++;
+        input->chop(1);
+    }
+    return digits;
+}
+
+time_t chop_timestamp(String_View *input)
+{
+    *input = input->trim();
+
+    expect_char(input, '[');
+    String_View hours = chop_digits(input);
+    expect_char(input, ':');
+    String_View minutes = chop_digits(input);
+    expect_char(input, ':');
+    String_View seconds = chop_digits(input);
+    expect_char(input, ']');
+
+    const time_t timestamp =
+        hours.as_integer<time_t>().unwrap * 60 * 60 +
+        minutes.as_integer<time_t>().unwrap * 60 +
+        seconds.as_integer<time_t>().unwrap;
+
+    return timestamp;
+}
+
+String_View chop_nickname(String_View *input)
+{
+    *input = input->trim();
+    expect_char(input, '<');
+    return input->chop_by_delim('>');
+}
+
 int main(int argc, char *argv[])
 {
-    if (argc < 5) {
-        fprintf(stderr, "Usage: ./vodus <gif_image> <png_image> <font> <output>\n");
+    if (argc < 6) {
+        fprintf(stderr, "Usage: ./vodus <log.txt> <gif_image> <png_image> <font> <output>\n");
         exit(1);
     }
 
-    const char *gif_filepath = argv[1];
-    const char *png_filepath = argv[2];
-    const char *face_file_path = argv[3];
-    const char *output_filepath = argv[4];
+    const char *log_filepath = argv[1];
+    const char *gif_filepath = argv[2];
+    const char *png_filepath = argv[3];
+    const char *face_file_path = argv[4];
+    const char *output_filepath = argv[5];
 
     FT_Library library;
     auto error = FT_Init_FreeType(&library);
@@ -386,9 +371,22 @@ int main(int argc, char *argv[])
             encode_avframe(context, frame, packet, output_stream);
         };
 
-    for (size_t i = 0; i < ARRAY_SIZE(messages); ++i) {
-        messages[i].timestamp = i;
+    // TODO(#35): log is not retrived directly from the Twitch API
+    //   See https://github.com/PetterKraabol/Twitch-Chat-Downloader
+    String_View input = file_as_string_view(log_filepath);
+    while (input.count > 0) {
+        assert(messages_size < VODUS_MESSAGES_CAPACITY);
+        String_View message = input.chop_by_delim('\n');
+        messages[messages_size].timestamp = (int) chop_timestamp(&message);
+        messages[messages_size].nickname = chop_nickname(&message);
+        messages[messages_size].message = message.trim();
+        messages_size++;
     }
+    messages_size = std::min(messages_size, 20lu);
+    std::sort(messages, messages + messages_size,
+              [](const Message &m1, const Message &m2) {
+                  return m1.timestamp < m2.timestamp;
+              });
 
     sample_chat_log_animation(face, encode_frame, &bttv);
 

+ 88 - 0
src/vodus_string.cpp

@@ -1,3 +1,10 @@
+template <typename T>
+struct Maybe
+{
+    bool has_value;
+    T unwrap;
+};
+
 // TODO(#20): String_View does not support unicode
 struct String_View
 {
@@ -70,6 +77,33 @@ struct String_View
 
         return result;
     }
+
+    template <typename Integer>
+    Maybe<Integer> as_integer() const
+    {
+        Integer sign = 1;
+        Integer number = {};
+        String_View view = *this;
+
+        if (view.count == 0) {
+            return {};
+        }
+
+        if (*view.data == '-') {
+            sign = -1;
+            view.chop(1);
+        }
+
+        while (view.count) {
+            if (!isdigit(*view.data)) {
+                return {};
+            }
+            number = number * 10 + (*view.data - '0');
+            view.chop(1);
+        }
+
+        return { true, number * sign };
+    }
 };
 
 String_View cstr_as_string_view(const char *cstr)
@@ -95,3 +129,57 @@ bool operator==(String_View view1, String_View view2)
     if (view1.count != view2.count) return false;
     return memcmp(view1.data, view2.data, view1.count) == 0;
 }
+
+String_View file_as_string_view(const char *filepath)
+{
+    assert(filepath);
+
+    size_t n = 0;
+    String_View result = {};
+    FILE *f = fopen(filepath, "rb");
+    if (!f) {
+        println(stderr, "Could not open file `", filepath, "`: ",
+                strerror(errno));
+        abort();
+    }
+
+    int code = fseek(f, 0, SEEK_END);
+    if (code < 0) {
+        println(stderr, "Could find the end of file ", filepath, ": ",
+                strerror(errno));
+        abort();
+    }
+
+    long m = ftell(f);
+    if (m < 0) {
+        println(stderr, "Could get the end of file ", filepath, ": ",
+                strerror(errno));
+        abort();
+    }
+    result.count = (size_t) m;
+
+    code = fseek(f, 0, SEEK_SET);
+    if (code < 0) {
+        println(stderr, "Could not find the beginning of file ", filepath, ": ",
+                strerror(errno));
+        abort();
+    }
+
+    char *buffer = new char[result.count];
+    if (!buffer) {
+        println(stderr, "Could not allocate memory for file ", filepath, ": ",
+                strerror(errno));
+        abort();
+    }
+
+    n = fread(buffer, 1, result.count, f);
+    if (n != result.count) {
+        println(stderr, "Could not read file ", filepath, ": ",
+                strerror(errno));
+        abort();
+    }
+
+    result.data = buffer;
+
+    return result;
+}