tag:blogger.com,1999:blog-26080312876314783892024-03-08T21:11:21.439+01:00Kalmi'snotes to himself and maybe othersUnknownnoreply@blogger.comBlogger10125tag:blogger.com,1999:blog-2608031287631478389.post-82502771424181921352020-02-17T17:55:00.000+01:002020-02-17T19:04:23.571+01:00Quick&dirty moving of a billion files from a single directoryI had more than a billion files in a single directory on a ZFS (on Linux) volume.<br />
<br />
If you got multiple computers with some simple naive software writing a small statistics log file every minute to a write-only shared directory, it is not hard to get there.<br />
<br />
Note that this is obviously not a good solution for logging, and I don't endorse this practice, but this is what we had, and simple commands like the following were no longer completing in reasonable time:<br />
<span style="font-family: "courier new" , "courier" , monospace;">cp /mnt/stat/data/2019_06_23_* /home/kalmi/incident_06_23/</span><br />
<br />
Running <span style="font-family: "courier new" , "courier" , monospace;">ls</span> or <span style="font-family: "courier new" , "courier" , monospace;">find</span> was taking "forever", and was affecting the performance of the rest of the system. I had never considered before that <span style="font-family: "courier new" , "courier" , monospace;">ls</span> by default has to load the whole directory into memory (or swap 👻) for sorting the entries.<br />
<br />
It was getting quite inconvenient. Something needed to be done, because I wanted to do some processing on some of the existing files, and for that I needed commands to complete in reasonable time.<br />
<br />
I decided to move the existing files into the following folder structure: <span style="font-family: "courier new" , "courier" , monospace;">year/month/day</span><br />
I decided I would write a Python script to do the job of moving the existing files. The original filenames contained a timestamp, and that's all that is needed to determine the destination. I couldn't find a Python library that allowed for unsorted listing of such large directories in reasonable time without buffering the whole thing. I expected to be able to just iterate with glob.glob, but it wasn't performing as expected.<br />
<br />
I already figured out earlier that <span style="font-family: "courier new" , "courier" , monospace;">ls</span> with right flags can do that, so I just piped the output of <span style="font-family: "courier new" , "courier" , monospace;">ls</span><span style="font-family: inherit;"> to my Python script that actually moved the files, and the following solution was born:</span><br />
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style>
<br />
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;">cd /mnt/stat/data && ls -p -1 -f | grep -v / |<span class="Apple-converted-space"> </span>python3 ../iter.py3</span><br />
<span class="s1" style="font-family: inherit;"><br /></span>
<span class="s1" style="font-family: inherit;">This previous line got added to cron, so that we wouldn't get to a billion files again.</span></div>
<div class="p1">
<br /></div>
<div class="p1">
<span class="s1" style="font-family: inherit;">The contents of iter.py3:</span></div>
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; min-height: 13.0px}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style>
<br />
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;">import fileinput</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;">import string</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;">import os</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;">import errno</span></div>
<div class="p2">
<span style="font-family: "courier new" , "courier" , monospace;"><span class="s1"></span><br /></span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;">for line in fileinput.input():</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>print(line.strip())</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>if len(line.strip().split('_')) != 4:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>print('SKIPPED')</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>continue</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>name, date, hour, ns = line.strip().split('_')</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>if len(date.split('-')) != 3:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>print('SKIPPED')</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>continue</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>year, month, day = date.split('-')</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>if not year.isdigit() or not month.isdigit() or not day.isdigit():</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>print('SKIPPED')</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>continue</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>try:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>os.mkdir(year)</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>except OSError as e:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>if e.errno == errno.EEXIST:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>pass</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>else:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>raise</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>try:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>os.mkdir(os.path.join(year,month))</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>except OSError as e:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>if e.errno == errno.EEXIST:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>pass</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>else:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>raise</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>try:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>os.mkdir(os.path.join(year,month,day))</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>except OSError as e:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>if e.errno == errno.EEXIST:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>pass</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>else:</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>raise</span></div>
<div class="p1">
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><span class="Apple-converted-space"> </span>os.rename(line.strip(), os.path.join(year,month,day,line.strip()))</span><br />
<span class="s1" style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span class="s1" style="font-family: inherit;">After running the script, the directory only contained a few folders, but running </span><span class="s1" style="font-family: "courier new" , "courier" , monospace;">ls</span><span class="s1" style="font-family: inherit;"> in that directory would still take a few seconds. It's interesting to me that the directory remained affected in this way. I guess ZFS didn't clean-up its now empty structures.</span></div>
<br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2608031287631478389.post-47950650886715961162019-12-12T22:21:00.000+01:002020-03-06T13:52:59.254+01:00startRealHiddenÉvekig rendszergazda voltam egy Internet Kávézóban, és egy napon úgy esett, hogy szükségem volt arra, hogy meglévő ablakos/konzolos alkalmazásokat teljesen rejtetten indítsak. Az is megeshetett, hogy ezek az alkalmazások futásuk során új ablakokat nyitottak még fel, és ezeknek se volt szabad megjelenniük.<br />
Erre kész megoldást nem találtam.<br />
<br />
Létezik egy <a href="http://technet.microsoft.com/en-us/sysinternals/cc817881.aspx" target="_blank">Desktops</a> nevű virtuális asztal kezelő Windowsra, ami működésében jelentősen eltér a többi virtuális asztal kezelőtől, márpedig abban, hogy nem úgy működik, hogy egyszerűen elrejti/megjeleníti az ablakokat, hanem ténylegesen külön <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682573(v=vs.85).aspx" target="_blank">Desktop</a>-okon futnak az alkalmazások. Ez egy nem széles körben ismert fogalom, így nem mond sokat szerintem senkinek, de mindjárt kifejtem.<br />
Ezek a Desktop-ok teljesen átjárhatatlan asztalok, és így a Desktops alkalmazásnak hátránya is van, mert nem lehet ablakokat mozgatni Desktop-ok közt, valamint például nem lehet 2 Desktop-on is egy-egy Firefox, mert a második nem indul el azzal a felkiáltással, hogy már már fut belőle egy, akivel nem tud kommunikálni.<br />
(Igen, tudom, hogy különböző fx profilokat igen is el lehet indítani a 2 külön Desktop-on.)<br />
Szokványos virtuális asztal kezelőknél egy új ablak mindig az aktuális asztalon jelenik meg, míg a Desktops esetén mindig ott jelenik meg, ahol az őt indító van.<br />
Az UAC is egy ilyen Desktop-ot hoz létre mikor besötétíti a képernyőt, és megjeleníti azt az ablakot:<br />
<a href="https://lh5.ggpht.com/-fpBT3u37p38/T-hxqqSKRWI/AAAAAAAAH8E/iGHRaA124yg/s1600-h/uac3%25255B5%25255D.png"><img alt="uac3" border="0" height="274" src="https://lh4.ggpht.com/-XrzBoqMEvl0/T-hxreOyk3I/AAAAAAAAH8M/7QiBRS7IqgQ/uac3_thumb%25255B2%25255D.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="uac3" width="471" /></a><br />
Ez miért jó az UAC-nak?<br />
A gonosz programok általában szeretnének rendszergazdaként futni. Ehhez át kell magukat küzdeni egy ilyen megerősítőablakon. Ha ezt a megerősítőablakot meg tudnák kerülni, akkor megkerülnék. Egy futó programból nagyon egyszerű egy adott gomb fölé mozgatni az egeret, és kattintani egyet. Az UAC készítői természetesen gondoltak erre, és ha fel kell dobniuk egy ilyen ablakot, akkor csinálnak egy képernyőképet az asztalról, és aztán átváltanak egy másik Desktop-ra, ahol megjelenítik a korábban készült képet, és ezt az ablakot. A Desktop-ok átjárhatatlansága miatt a gonosz program nem tud az UAC által létrehozott Desktop-on egérmozgást programból előidézni. (Valamint azt hiszem, hogy másik user alatt is fut az UAC ablak.)<br />
<br />
Térjünk is vissza az eredeti témánkra: Szóval szükségem volt valamire, ami rejtettem el tud indítani csúnya fekete ablakokat (vagy bármit).<br />
Az általam készített megoldás a startRealHidden.<br />
A startRealHidden a Desktops módszerét használja fel, és egy külön Desktopon indítja el a kívánt alkalmazást, amely így egyáltalán nem jelenik meg, és az általa indított dolgok se.<br />
A lelke a dolognak (C#):<br />
<pre style="background: rgb(255, 255, 255); border-color: initial; border-style: solid; border-width: 1px;"><span style="color: maroon; font-weight: bold;">namespace</span> startRealHidden
<span style="color: purple;">{</span>
<span style="color: maroon; font-weight: bold;">class</span> Program
<span style="color: purple;">{</span>
<span style="color: maroon; font-weight: bold;">static</span> <span style="color: maroon; font-weight: bold;">void</span> Main<span style="color: #808030;">(</span><span style="color: maroon; font-weight: bold;">string</span><span style="color: #808030;">[</span><span style="color: #808030;">]</span> args<span style="color: #808030;">)</span>
<span style="color: purple;">{</span>
Desktop desktop <span style="color: #808030;">=</span> Desktop<span style="color: #808030;">.</span>CreateDesktop<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #0000e6;">myDesktop</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span><span style="color: purple;">;</span>
Process p <span style="color: #808030;">=</span> desktop<span style="color: #808030;">.</span>CreateProcess<span style="color: #808030;">(</span>String<span style="color: #808030;">.</span>Join<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #0000e6;"> </span><span style="color: maroon;">"</span><span style="color: #808030;">,</span> args<span style="color: #808030;">)</span><span style="color: #808030;">)</span><span style="color: purple;">;</span>
p<span style="color: #808030;">.</span>WaitForExit<span style="color: #808030;">(</span><span style="color: #808030;">)</span><span style="color: purple;">;</span>
<span style="color: purple;">}</span>
<span style="color: purple;">}</span>
<span style="color: purple;">}</span></pre>
<br />
A Desktop osztályt itt találhatjátok: <a href="http://www.codeproject.com/Articles/7666/Desktop-Switching">http://www.codeproject.com/Articles/7666/Desktop-Switching</a><br />
<br />
<strong>Használat: </strong><span style="font-family: "courier new" , "courier" , monospace;">startRealHidden spawnBunchOfWindowsThatGoAwayOnTheirOwn.bat arg1 arg2 arg3</span><br />
<br />
Egy jelentős limitáció van, és az az, hogy nem lehet egér/billentyűzet interakciót szimulálni nem aktív Desktop-on, tehát mondjuk egy interakciót szimuláló AutoIt szkript nem fog menni rejtetten.<br />
<br />
<a href="https://www.dropbox.com/s/nh8bmx5smsje1l7/startRealHidden.zip?dl=1" target="_blank">Projekt letöltése</a>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2608031287631478389.post-34875742819319682202016-08-05T14:09:00.001+02:002017-04-28T13:28:46.234+02:00Quick&Dirty locally-trusted self-signed HTTPS on IIS on Win10<p>Run PowerShell as admin, then run:<br><font face="Consolas">New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -Subject my-domain.com -Type SSLServerAuthentication –DnsName my-domain.com,somesubdomain.my-domain.com<br></font><strong>(replace my-domain.com with your own domain)</strong></p> <p>Go to the “Server Certificates” page in IIS Manager, right click on your new cert, select “View”, go to the “Details” tab, click the “Copy to file” button, just keep clicking next until it asks for a file name, then just save it somewhere.</p> <p>Open the newly saved certificate, and click the “Install certificate” button, and install it into the current user’s “Trusted Root Certificate Authorities” store (Automatic store selection won’t do.).</p> <p>Go back to IIS Manager, select your site, go to its Bindings, click “Add”, enter your domain, select “https” in the dropdown, and just select your cert.</p> <p>Make sure to add the domain to the hosts file pointing to 127.0.1!</p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2608031287631478389.post-82240358360196562872016-08-04T22:48:00.001+02:002016-08-04T22:48:32.623+02:00Export all the drivers!<p>TIL you can export all your third-party drivers from PowerShell:<br>Export-WindowsDriver -Online -Destination e:\drivers_go_here</p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2608031287631478389.post-31466631701019961112015-12-20T06:17:00.001+01:002017-05-19T19:33:37.653+02:00What goes into an IPFS multihash (in case of a file)<p>I started fooling around with a simple python multihash library, and I wanted to verify that it produced the same multihash as the go-ipfs reference implementation. <p>I created a <em>hashme.txt</em> with the following content: <em>Hash me!<br></em>Then I called ”ipfs”, so that I would get a multihash: <p><font face="Consolas">> ipfs add hashme.txt<br>added QmNdTrvTHNM4tXjeoX1HD554eMTweTN91hf2ih6KKwXppo hashme.txt</font> <p><em> <p></em>I assumed that this hash would match the return value from the python multihash library when calling it like this: <p><font face="Consolas">>>> someMultihashLib.gen_hash(SHA_256, ‘Hash me!’)</font> <p>I did not. My assumption was quite naive. <p>I wanted to see what the block (referenced by the QmNd… hash) actually contained, so I used <em>ipfs block get</em> to get the raw content of the block into a file: <p><font face="Consolas">> ipfs block get QmNdTrvTHNM4tXjeoX1HD554eMTweTN91hf2ih6KKwXppo > block.raw</font> <p>Then I checked the content of this file from python: <p><font face="Consolas">>>> open('block.raw').read()<br>'\n\x0e\x08\x02\x12\x08Hash me!\x18\x08'</font> <p>Okay, the “<em>Hash me!</em>” text is there as expected, but there is also some other stuff. <p>At this point after some light code browsing I found <a href="https://github.com/ipfs/go-ipfs/blob/master/merkledag/pb/merkledag.proto">merkledag.proto</a>, which I downloaded. So.. IPFS uses protobuf for serialization, so I got myself a <em>protoc</em> executable, and put it on my path. This is actually my first time using protobuf. <p>I assumed that the encapsulation could be an <em>PBNode </em>type from the previously found <em>merkledag.proto</em> file (It being a <em>PBLink</em> (referencing something else) wouldn’t make much sense, and this .proto file only contains these 2 types.), so here my first decoding attempt of <em>block.raw</em>: <p><font face="Consolas">> protoc --decode=PBNode merkledag.proto < block.raw<br>Data: "\010\002\022\010Hash me!\030\010"</font> <p>It’s… um… a partial success. It could make sense. Instances of the <em>PBNode </em>type can only contain some number of Links (of type <em>PBLink</em>) and Data (of type bytes), and this one only contains data, but it is still encapsulated in something. <p>I tried the --decode_raw switch, and it seems like that protoc has decided by some heuristic that the bytes of the Data are not actually of just simple bytes, but something that it “understands”. Outer “1” key identifies <em>PBNode’</em>s Data. The inner 1,2,3 key-value pairs are a mystery for now. <p><font face="Consolas">>protoc --decode_raw < block.raw<br>1 {<br> 1: 2<br> 2: "Hash me!"<br> 3: 8<br>}</font> <p>So I assumed the content of the Data field is also serialized with protobuf, but some other <em>.proto</em> file. I searched the go-ipfs codebase for <em>.proto</em> files, and the one that looked most promising was <a href="https://github.com/ipfs/go-ipfs/blob/master/unixfs/pb/unixfs.proto">unixfs.proto</a>. <p>It makes perfect sense since I actually added a file. This .proto file contains a <em>Data</em> type, that has the following field: <em></em> <ul> <li><em>Type</em>(key #1, and the value, “2” stands for File) <li><em>Data</em>(key#2, yup, it’s “Hash me!”) <li><em>filesize</em>(key#3, and yes, “Hash me!” string is actually 8 bytes long!) <li>and some other(s) fields that are irrelevant for this post…</li></ul> <p>So, to summarize: When calling the ”<em>ipfs add” </em>command, that data is first wrapped in the <em>Data</em> type from <em>unixfs.proto</em>, then the result is wrapped in a <em>PBNode</em> from <em>merkledag.proto</em>. <p>In hindsight, I should have used ”<em>ipfs block put”</em> to verify the python multihash implementation. The output of ”<em>ipfs block put hashme.txt” </em>matches the return value from the python library. Still, this was an interesting exploration.</p> <p><strong>Update:</strong> this post contains some inaccuracies and/or omissions, such as: protoc does not use heuristics, and data may be chunked when it is longer</p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2608031287631478389.post-58745167259037267962013-07-17T03:54:00.000+02:002013-07-17T03:58:03.188+02:00How to get FlatOut 2 LAN multiplayer working over HamachiFlatOut 2 LAN multiplayer broadcasts UDP packets on the NIC with the lowest metric. <span style="font-size: x-small;">(or at least the discovery part)</span><br />
<span style="font-size: x-small;"><br /></span>
So all you got to do is set the "Hamachi" interface's metric to a small value, like 1.<br />
Network Adapters->Hamachi->Properties->ipv4->Properties->Advanced->Metric<br />
<br />
(And of course don't forget to take care of the firewall.)<br />
(Also don't forget to change it back when you are finished playing.)Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2608031287631478389.post-3888906827508800732013-05-31T22:40:00.000+02:002020-03-05T18:52:43.690+01:00Teredo szimmetrikus NAT mögülHohó, még régebben egy csomót vacakoltam azzal, hogy Teredo-t valahogy életre keltsem az otthoni asztali gépemen, és most Windows 7-en sikerült.<br />
<br />
<h3>
A végeredmény</h3>
<div>
<pre style="background-color: black; color: white; padding: 10px;"><span style="font-family: "courier new" , "courier" , monospace;">C:\Users\Kalmi>ping -6 ipv6.google.com
ipv6.l.google.com [2a00:1450:4016:802::1011] pingelése - 32 bájtnyi adattal:
Válasz 2a00:1450:4016:802::1011: idő=50 ms
Válasz 2a00:1450:4016:802::1011: idő=50 ms
Válasz 2a00:1450:4016:802::1011: idő=58 ms
Válasz 2a00:1450:4016:802::1011: idő=51 ms
2a00:1450:4016:802::1011 ping-statisztikája:
Csomagok: küldött = 4, fogadott = 4, elveszett = 0
(0% veszteség),
Oda-vissza út ideje közelítőlegesen, milliszekundumban:
minimum = 50ms, maximum = 58ms, átlag = 52ms</span></pre>
<br />
<pre style="background-color: black; color: white; padding: 10px;"><span style="font-family: "courier new" , "courier" , monospace;">C:\Windows\system32>netsh interface teredo show state
Teredo-paraméterek
---------------------------------------------
Típus: client
Kiszolgálónév: teredo.niif.hu
Ügyfél frissítési időköze: 60 másodperc
Ügyfélport : 34567
Állapot : qualified
Ügyféltípus : teredo client
Hálózat : unmanaged
Hálózati címfordítás (NAT): restricted
Speciális hálózati címfordítás: UPNP: Nem, Portmegőrzés: Igen
Helyi leképezés: 192.168.100.57:34567
Külső NAT-leképezés: 86.59.189.185:34567</span></pre>
</div>
<h3>
A folyamat</h3>
<div>
Az első lépés, amit elkövettem, az az volt, hogy megnyomtam uTorrent-ben a <i>Settings>Connections>Install IPv6/Teredo</i> gombot. Ez nem tudom, hogy pontosan mit csinált, de <a href="http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx" target="_blank">procexp</a>-ben azt láttam, hogy netsh paracsot futtat. Gondolom csak engedélyezte a Teredo-t.</div>
<div>
<br /></div>
<div>
Ezen a ponton nem meglepő módon még nem működött a Teredo tunnel, mert a gépem szimmetrikus NAT mögött van, és azzal köztudottan nem működik együtt a Teredo.</div>
<div>
<br /></div>
<div>
Hasraütöttem, és kiválasztottam ügyfélportnak egy portot, amit <b>beállítottam forwardingolásra</b> a routeremen, valamint az asztali gépemen is beállítottam ügyfélportnak:</div>
<div>
<span style="background-color: white; color: #404040; font-family: "roboto" , "arial" , sans-serif; font-size: 13px; line-height: 18px;"> </span><i style="background-color: white; color: #404040; font-family: Roboto, arial, sans-serif; font-size: 13px; line-height: 18px;">netsh</i><span style="background-color: white; color: #404040; font-family: "roboto" , "arial" , sans-serif; font-size: 13px; line-height: 18px;"> (in a console run as administrator)</span><br />
<span style="background-color: white; color: #404040; font-family: "roboto" , "arial" , sans-serif; font-size: 13px; line-height: 18px;"> </span><i style="background-color: white; color: #404040; font-family: Roboto, arial, sans-serif; font-size: 13px; line-height: 18px;">interface</i><br />
<span style="background-color: white; color: #404040; font-family: "roboto" , "arial" , sans-serif; font-size: 13px; line-height: 18px;"> </span><i style="background-color: white; color: #404040; font-family: Roboto, arial, sans-serif; font-size: 13px; line-height: 18px;">teredo</i><br />
<span style="background-color: white; color: #404040; font-family: "roboto" , "arial" , sans-serif; font-size: 13px; line-height: 18px;"> </span><i style="background-color: white; color: #404040; font-family: Roboto, arial, sans-serif; font-size: 13px; line-height: 18px;">set state clientport=XXXXX</i><br />
<span style="background-color: white; color: #404040; font-family: "roboto" , "arial" , sans-serif; font-size: 13px; line-height: 18px;"> </span><i style="background-color: white; color: #404040; font-family: Roboto, arial, sans-serif; font-size: 13px; line-height: 18px;">show state</i><span style="background-color: white; color: #404040; font-family: "roboto" , "arial" , sans-serif; font-size: 13px; line-height: 18px;"> (just to check)</span><br />
<span style="background-color: white; color: #404040; font-family: "roboto" , "arial" , sans-serif; font-size: 13px; line-height: 18px;"> </span><i style="background-color: white; color: #404040; font-family: Roboto, arial, sans-serif; font-size: 13px; line-height: 18px;">exit</i></div>
<div>
<br /></div>
<div>
Ezen a ponton már működnie kell a <i>ping -6 ipv6.google.com</i>-nak, viszont alapból a Microsoft Teredo szervere van beállítva kiszolgálónak, ami nem ideális, mert messze van.</div>
<div>
A következő paranccsal beállíthatjuk a <a href="http://www.niif.hu/adath_l_zat/hbone/teredo" target="_blank">NIIF magyar Teredo szerverét</a> kiszolgálónak:</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">netsh interface teredo set state client teredo.niif.hu 60 34567</span></div>
<div>
<br /></div>
<div>
Forrás: <a href="https://plus.google.com/107170836901331596770/posts/Q3bsqo7WHGt" target="_blank">Andrea Riva's G+ post</a></div>
Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2608031287631478389.post-79958613444692242882012-07-21T01:04:00.000+02:002013-05-31T17:07:50.913+02:00OTP egyenleget naponta Google Docs-ba automatikusan<b>Update:</b> Téma erről a posztról HUP-on: <a href="http://hup.hu/node/120903">http://hup.hu/node/120903</a><br /><br />
<h3>
Előzmény</h3>
Egy szép nyáron napon volt pár e-mail a Gmail fiókomban, amikkel csak 1 hét múlva kellett volna valamit kezdenem, és zavart, hogy ennek ellenére minden nap ott néznek rám. Egy kis guglizással rátaláltam erre:<br />
<a href="http://lifehacker.com/5825634/how-to-add-a-snooze-button-to-gmail-no-extensions-required">http://lifehacker.com/5825634/how-to-add-a-snooze-button-to-gmail-no-extensions-required</a><br />
Már a cikk címe felkeltette a érdeklődésem, mert elképzelésem nem volt, hogy hogyan lehetséges ez bármiféle kiterjesztés vagy harmadik félnek történő jelszókiadás nélkül.<br />
Lehetséges, és a varázslat része a dolognak a Google Scripts, ami lehetővé teszi számunkra, hogy minden nap megadott időben lefutó javascript nyelvű felhőben tárolt scripteket írjunk, amik nagyon kényelmes javascriptes api-n hozzáférhetnek Google szolgáltatásainkhoz, mint például a Gmailhez vagy a Docs-hoz.<br />
Ennek a scriptnek a kódjáról nem fogok beszélni. Ha érdekel, akkor megtalálod az eredeti linken.<br />
<h3>
</h3>
<h3>
</h3>
<h3>
</h3>
<h3>
Kényszer</h3>
Aztán jött a kényszer, hogy valamire használnom kell ezt a Google Script-et a Gmail Snooze-on felül.. Itt jött az ötlet, hogy milyen király(?) lenne, ha láthatnám a banki egyenlegem alakulását egy grafikonon Google Docsban.<br />
<h3>
</h3>
<h3>
</h3>
<h3>
</h3>
<h3>
Kérés</h3>
Az OTP biztosít egy a normál netbanktól független felületet, ahol a telekóddal és kártyaszámmal le lehet kérdezni az aktuális egyenleget. A telekód alapból a számlaszám utolsó 3 számjegye. Ez a felület az OTPdirekt belépés gomb alatt található jelenleg:<br />
<a href="https://www.otpbank.hu/portal/hu/Egyenleglekerdezes" target="_blank"><img alt="OTP-egyenleg" border="0" src="http://lh5.ggpht.com/-uU9MRik02vc/T-yRm_n5OxI/AAAAAAAAH8Y/uBhtQI9U47E/OTP-egyenleg6.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="OTP-egyenleg" /></a><br />
<a href="https://www.otpbank.hu/portal/hu/Egyenleglekerdezes" target="_blank">Direkt link az OTP egyenleglekérdezés leírására</a><br />
<span style="background-color: white;"><br /></span>
<span style="background-color: white;">Itt a kártyaszám és a telekód megadása utána megkaphatjuk az aktuális egyenlegünk:</span><br />
<a href="http://lh6.ggpht.com/-33SCpKF_V1o/UAnidYnHA2I/AAAAAAAAH9g/hnylQIdRxDc/s1600-h/image36.png"><img alt="image[3]" border="0" height="147" src="http://lh4.ggpht.com/-rdBD35NK5N4/UAnieCh-LQI/AAAAAAAAH9k/t6WQn5Ry9Is/image3_thumb3.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image[3]" width="424" /></a><br />
Hm… Ezt a lekérdezést szeretnénk valahogy automatizálni.<br />
<br />
Nézzük meg az űrlapot, ami beküldünk:<br />
<span style="font-size: xx-small;">(Chrome-ban dolgozom.)</span><br />
<a href="http://lh3.ggpht.com/-Ihh_-mQ_xgM/T-yRpWlp2GI/AAAAAAAAH8o/HXvFOWLcHoQ/s1600-h/image12.png"><img alt="image" border="0" src="http://lh4.ggpht.com/-CuKDmLvBGto/T-yRrfwaABI/AAAAAAAAH8s/8bE55Fg5mhQ/image_thumb8.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
Katt az “Elem megtekintésére”.<br />
Ekkor a Chrome feldobja az Elements Panel-t:<br />
<a href="http://lh6.ggpht.com/-_8Xfn4-sZu8/T-yRsq__M3I/AAAAAAAAH84/q2OeuQ1dx3o/s1600-h/image17.png"><img alt="image" border="0" src="http://lh6.ggpht.com/-PazIEACTvL8/T-yRtxdSmpI/AAAAAAAAH9A/SpXapsXvgmY/image_thumb11.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
A <span style="background-color: #cccccc;">method=”post”</span>-ból láthatjuk, hogy ez egy POST kérés lesz. A kérésben a következő mezők fognak utazni:<br />
muvelet<br />
azonosito<br />
telekod<br />
honlapAzonosito<br />
azonositoxx<br />
telekodxx<br />
<br />
Ezekből mi csak kettőnek állítjuk az értékét, és értelemszerűen ezek az azonositoxx és telekodxx. A többit alapértéken hagyjuk.<br />
Valójában ha jobban megnézzük, akkor tévedtem, mert az azonositoxx és a telekodxx az beküldéskor üres lesz az onsubmit eseménykezelő hatására, és a tartalmuk átíródik a rejtett azonosito es telekod mezőkbe. (Ezt azért csinálták, mert nem akarták, hogy a böngésző felajánlhassa a jelszó elmentését, valamint így a Vissza gomb megnyomása után a böngésző nem tudja visszaállítani a kitöltött állapotát az űrlapnak.)<br />
<br />
Eddig feltételezésink helyességéről meggyőződhetünk, ha elkezdjük figyelni az oldal forgalmát a Network fülön, és beküldünk egy kérést.<br />
Ehhez váltsunk át a Network fülre (Az Elements fültől 2-vel jobbra.), és aztán a szokványos módon küldjük be az űrlapot. Ezután kattintsuk rá a “bankkartyaEgyenlegLekerdezes” kérésre, és keressük a Form Data részt.<br />
<a href="http://lh4.ggpht.com/-Md1JimeTbcQ/UAnienfAn5I/AAAAAAAAH9w/FSTVyE9Oog4/s1600-h/image61.png"><img alt="image" border="0" src="http://lh5.ggpht.com/-epWGMOvZwlc/UAnif6NEumI/AAAAAAAAH94/8cYrdwft5Vk/image_thumb4%25255B1%25255D.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
Úgy tűnik, hogy mindent helyesen láttunk.<br />
Kipróbálhatjuk mondjuk wget-el (opcionális):<br />
<span style="font-family: Consolas;">wget https://www.otpbankdirekt.hu/homebank/do/bankkartyaEgyenlegLekerdezes -O - --post-data "muvelet=login&azonosito=██████████&telekod=███&honlapAzonosito=Default.User&azonositoxx=&telekodxx="<br />(Ez a parancs egy sor.)</span><br />
<br />
Ha minden jól sikerült, akkor a wget hatására láthatjuk a lekérdezés eredményét egy csomó html kód közt.<br />
<span style="background-color: white;"><br /></span>
<span style="background-color: white;">Megvan, hogy hogyan tudjuk lekérdezni. Akkor most ebből valahogy Google Script-et kéne csinálni.</span><br />
<h3>
</h3>
<h3>
Script</h3>
Hozzunk létre egy új Google Táblázatot, nyissuk meg, és az Eszközök menüből válasszuk ki a Script szerkesztőt. Ekkor kapunk egy nagyon segítőkész ablakot, amit csukjunk is be.<br />
<br />
Ekkor ezt kell látnunk:<br />
<a href="http://lh4.ggpht.com/-fXiDyl_ESiQ/UAnigrp422I/AAAAAAAAH98/AM_e_MXPSjw/s1600-h/image5.png"><img alt="image" border="0" src="http://lh4.ggpht.com/-0hD8X0zzx6U/UAnihckFtJI/AAAAAAAAH-I/9-_5uiryAfQ/image_thumb2.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
A kis “Play” gombbal lefuttathatjuk a myFuncton-t, ami jelenleg nem csinál semmit. (Ekkor el kell mentenünk a Project-et. Mentsük tetszőleges néven.)<br />
<br />
Csináljunk valami extravangásabbat:<br />
<a href="http://lh3.ggpht.com/-3nqEmVpymok/UAnijFWJ8SI/AAAAAAAAH-Q/sVGkMb80qBc/s1600-h/image10.png"><img alt="image" border="0" src="http://lh4.ggpht.com/-cRwSsQC2Y-c/UAnijnmoQnI/AAAAAAAAH-Y/ArZTcZb__vg/image_thumb5.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
<br />
Mikor ezt lefuttatjuk, akkor első pillantásra nem történik semmi, pedig valójában megjelent egy üzenetablak, de nem ott ahol vártuk, hanem az eredeti dokumentumban:<br />
<br />
<a href="http://lh4.ggpht.com/-Tdc1BcPJ2ug/UAnikuJMBwI/AAAAAAAAH-g/ngy0PrlPzK8/s1600-h/image15.png"><img alt="image" border="0" src="http://lh4.ggpht.com/-hC9Jw_dLCkg/UAnilc-lX8I/AAAAAAAAH-o/OMajbQA_nyc/image_thumb81.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
<br />
Az elérhető API-kat itt találod: <a href="https://developers.google.com/apps-script/defaultservices">https://developers.google.com/apps-script/defaultservices</a><br />
<br />
Például megtalálhatjuk a <a href="https://developers.google.com/apps-script/class_urlfetchapp#fetch" target="_blank">UrlFetchApp.fetch</a> metódust, ami jó szolgálatot fog nekünk tenni. Ezzel fogjuk lekérni az egyenlegünket.<br />
A korábban összehozott lekérés és a dokumentáció alapján a következő kódot állítjuk elő:<br />
<a href="http://lh4.ggpht.com/-yQ1S5Ba2Isw/UAnimXh1C4I/AAAAAAAAH-w/bTT35jYJ5mM/s1600-h/image20.png"><img alt="image" border="0" src="http://lh3.ggpht.com/-qzBiQnRhzRc/UAninPH1BiI/AAAAAAAAH-4/gMpcuKfL5Hc/image_thumb111%25255B1%25255D.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
<br />
Ez ugyanaz a lekérés, ami korábban kipróbáltunk. Próbáljuk ki itt is:<br />
<a href="http://lh6.ggpht.com/-Rj6erxwHebU/UAnioOvo2lI/AAAAAAAAH_A/xqg2fnihCto/s1600-h/image32.png"><img alt="image" border="0" src="http://lh4.ggpht.com/-jqe7bH8nQ1A/UAnio4IjiVI/AAAAAAAAH_I/Bb8XYBUavhs/image_thumb19.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
<br />
… és az eredmény:<br />
<a href="http://lh6.ggpht.com/-vhHxdq5w5yI/UAniqEpc-6I/AAAAAAAAH_Q/ABO7gng8MP8/s1600-h/image27.png"><img alt="image" border="0" src="http://lh4.ggpht.com/-7vwzwH7ontk/UAniq70_hmI/AAAAAAAAH_Y/NLBSTh_p6T8/image_thumb16.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
A lekérés a title alapján működni látszik….. Már csak valahogy ki kéne nyerni belőle a lényeget. Html-ből infót kinyerni nem szép, de hasznos.<br />
<br />
A következő buta, de működő megoldást választottam: Az első <span style="background-color: #cccccc; font-family: Consolas;"><span class="value"><strong></span> és <span style="background-color: #cccccc; font-family: Consolas;"></strong></span> közötti cucc érdekel minket:<br />
<span style="background-color: #cccccc; font-family: Consolas;">var egyenleg = response.getContentText().split('<span class="value"><strong>')[1].split("</strong>")[0];</span><br />
<span style="background-color: #cccccc; font-family: Consolas;"><br /></span>
Valamint még a pontot is kéne kapni belőle, mert számot szeretnénk:<br />
<span style="background-color: #cccccc; font-family: Consolas;">var egyenleg = response.getContentText().split('<span class="value"><strong>')[1].split("</strong>")[0].replace(".","");</span><br />
<span style="background-color: #cccccc; font-family: Consolas;"><br /></span>
Így a következő tesztelhető kódhoz jutunk:<br />
<a href="http://lh5.ggpht.com/-AjODVxfZ30w/UAnirwVg-qI/AAAAAAAAH_c/kOiiN7wFa4g/s1600-h/image39.png"><img alt="image" border="0" src="http://lh6.ggpht.com/-fSIeWWPk1BQ/UAnisstKIjI/AAAAAAAAH_k/fJJMiHL__qE/image_thumb24.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
<br />
… amit ha lefuttatunk, akkor most már ténylegesen az egyenlegünket kapjuk a dobozba:<br />
<a href="http://lh4.ggpht.com/-fM_OWF0GsZU/UAniuPOeEeI/AAAAAAAAH_w/IIk_OxavriE/s1600-h/image45.png"><img alt="image" border="0" src="http://lh3.ggpht.com/-CAmjU_kgLjU/UAnivOLxIkI/AAAAAAAAH_4/vin3IvtzPOk/image_thumb28.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
<br />
Ez szép és jó, de mi grafikont szeretnénk.<br />
<br />
A grafikonhoz először meg lennie az adatnak táblázatosan. Mondjuk így:<br />
<a href="http://lh6.ggpht.com/-olzHP2zMWas/UAniv5xR2YI/AAAAAAAAIAA/mphPK7hXOo0/s1600-h/image61%25255B1%25255D.png"><img alt="image" border="0" src="http://lh3.ggpht.com/-tSQ6ynY2N5U/UAniwsubHNI/AAAAAAAAIAE/LXI8FUQRf2k/image_thumb7.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
<br />
Ezután kijelöljük az A és B oszlopot egyszerre, és hozzáadunk a dokumentumhoz egy vonaldiagramot. Azon kicsit állítgatunk, és akkor valami ilyesmit kaphatunk:<br />
<a href="http://lh4.ggpht.com/-vfC-b1hatJ8/UAnixeXRqOI/AAAAAAAAIAM/ldeJj6Dyg2A/s1600-h/image121.png"><img alt="image" border="0" src="http://lh5.ggpht.com/-bdOJomlJnm0/UAniyI8j23I/AAAAAAAAIAU/u7fejzBdUTs/image_thumb111.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
Azért volt fontos az egész A és B oszlopot kijelölni, mert így ha egy új sorba beleírunk valamit, akkor így az is felkerül a diagramra, és így akkor most már tényleg csak az a magic kell, ami minden nap hozzáad egy új sort ehhez a táblázathoz a megfelelő értékekkel.<br />
<br />
Az eddig elkészült függvényünket alakítsuk át egy segédfüggvénnyé, ami az egyenleggel tér vissza visszatérési értékként. Ehhez egyszerűen cseréljük le az msgBox-os sort erre:<br />
<span style="font-family: Consolas;">return egyenleg;</span><br />
<span style="font-family: Consolas;"><br /></span>
Ezután írjuk meg a következő függvényt, ami hozzáadja a megfelelő értékekkel rendelkező új sort:<br />
<a href="http://lh3.ggpht.com/-soFjRGybHxI/UAniy1Wi9UI/AAAAAAAAIAc/shTbmiUxYbQ/s1600-h/image171.png"><img alt="image" border="0" src="http://lh3.ggpht.com/-YcNr20qt-dU/UAnizvbTrEI/AAAAAAAAIAk/Cj6HweFxgMQ/image_thumb14.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
<span style="background-color: white;"><br /></span>
<span style="background-color: white;">Láthatjuk, hogy ez felhasználja korábban megírt getOtpEgyenleg függvényünket.</span><br />
Az “otp-egyenleg” a munkalap neve. Ez neked lehet, hogy más.<br />
A dátumot azért ilyenre formázom, mert (többek közt?) ezt ismeri fel a Docs dátumnak.<br />
<br />
Ha ezt a függvényt lefuttatjuk a kis Play gombbal, akkor láthatjuk, hogy hozzáadódik egy új sor a táblázathoz, és a diagram is frissül.<br />
<br />
Egyetlen lépés van már csak hátra: Beállítani, hogy minden este automatikusan lekérje az aktuális egyenleget:<br />
Resources menü → Current script’s triggers → és ott adjuk hozzá a következő sort:<br />
<a href="http://lh6.ggpht.com/-qgqgmtkkbb4/UAni0CU80WI/AAAAAAAAIAw/sJzU7ETkQ6Q/s1600-h/image23.png"><img alt="image" border="0" src="http://lh6.ggpht.com/-xbUV2-8gUEk/UAni01nlZgI/AAAAAAAAIA4/DBCiWmW-kz4/image_thumb21.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a><br />
<br />
Mentsük, és ezzel készen is vagyunk. Minden éjjel magától frissülni fog a táblázatunk. :)<br />
<span style="color: red; font-size: medium;"><strong><br /></strong></span>
<span style="color: red; font-size: medium;"><strong>Yéy!</strong></span><br />
<h3>
</h3>
<h3>
</h3>
<h3>
A kód másolható formában</h3>
<pre style="-webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: white; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px;"><span style="font-family: Consolas;"><span style="color: maroon;"><strong>function</strong></span> getOtpEgyenleg<span style="color: #808030;">()</span> <span style="color: purple;">{</span>
<span style="color: maroon;"><strong>var</strong></span> url <span style="color: #808030;">=</span> <span style="color: maroon;">"</span><span style="color: #0000e6;">https://www.otpbankdirekt.hu/homebank/do/bankkartyaEgyenlegLekerdezes</span><span style="color: maroon;">"</span><span style="color: purple;">;</span>
<span style="color: maroon;"><strong>var</strong></span> payload <span style="color: #808030;">=</span>
<span style="color: purple;">{</span>
<span style="color: maroon;">"</span><span style="color: #0000e6;">muvelet</span><span style="color: maroon;">"</span> <span style="color: purple;">:</span> <span style="color: maroon;">"</span><span style="color: #0000e6;">login</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span>
<span style="color: maroon;">"</span><span style="color: #0000e6;">azonosito</span><span style="color: maroon;">"</span> <span style="color: purple;">:</span> <span style="color: maroon;">"</span><span style="color: #0000e6;">██████████</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span>
<span style="color: maroon;">"</span><span style="color: #0000e6;">telekod</span><span style="color: maroon;">"</span> <span style="color: purple;">:</span> <span style="color: maroon;">"</span><span style="color: #0000e6;">███</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span>
<span style="color: maroon;">"</span><span style="color: #0000e6;">honlapAzonosito</span><span style="color: maroon;">"</span> <span style="color: purple;">:</span> <span style="color: maroon;">"</span><span style="color: #0000e6;">Default.User</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span>
<span style="color: maroon;">"</span><span style="color: #0000e6;">azonositoxx</span><span style="color: maroon;">"</span> <span style="color: purple;">:</span> <span style="color: maroon;">""</span><span style="color: #808030;">,</span>
<span style="color: maroon;">"</span><span style="color: #0000e6;">telekodxx</span><span style="color: maroon;">"</span> <span style="color: purple;">:</span> <span style="color: maroon;">""</span>
<span style="color: purple;">};</span>
<span style="color: maroon;"><strong>var</strong></span> options <span style="color: #808030;">=</span>
<span style="color: purple;">{</span>
<span style="color: maroon;">"</span><span style="color: #0000e6;">method</span><span style="color: maroon;">"</span> <span style="color: purple;">:</span> <span style="color: maroon;">"</span><span style="color: #0000e6;">post</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span>
<span style="color: maroon;">"</span><span style="color: #0000e6;">payload</span><span style="color: maroon;">"</span> <span style="color: purple;">:</span> payload
<span style="color: purple;">};</span>
<span style="color: maroon;"><strong>var</strong></span> response <span style="color: #808030;">=</span> UrlFetchApp<span style="color: #808030;">.</span>fetch<span style="color: #808030;">(</span>url<span style="color: #808030;">,</span> options<span style="color: #808030;">)</span><span style="color: purple;">;</span>
<span style="color: maroon;"><strong>var</strong></span> egyenleg <span style="color: #808030;">=</span> response<span style="color: #808030;">.</span>getContentText<span style="color: #808030;">().</span><span style="color: maroon;"><strong>split</strong></span><span style="color: #808030;">(</span><span style="color: #0000e6;">'<span class="value"><strong>'</span><span style="color: #808030;">)[</span><span style="color: #008c00;">1</span><span style="color: #808030;">].</span><span style="color: maroon;"><strong>split</strong></span><span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #0000e6;"></strong></span><span style="color: maroon;">"</span><span style="color: #808030;">)[</span><span style="color: #008c00;">0</span><span style="color: #808030;">].</span><span style="color: maroon;"><strong>replace</strong></span><span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #0000e6;">.</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span><span style="color: maroon;">""</span><span style="color: #808030;">)</span><span style="color: purple;">;</span>
<span style="color: maroon;"><strong>return</strong></span> egyenleg<span style="color: purple;">;</span>
<span style="color: purple;">}</span>
<span style="color: maroon;"><strong>function</strong></span> updateSpreadSheetWithNewRow<span style="color: #808030;">()</span> <span style="color: purple;">{</span>
<span style="color: maroon;"><strong>var</strong></span> egyenleg <span style="color: #808030;">=</span> getOtpEgyenleg<span style="color: #808030;">()</span><span style="color: purple;">;</span>
<span style="color: maroon;"><strong>var</strong></span> date <span style="color: #808030;">=</span> Utilities<span style="color: #808030;">.</span>formatDate<span style="color: #808030;">(</span><span style="color: maroon;"><strong>new</strong></span> <span style="color: #797997;">Date</span><span style="color: #808030;">(),</span> <span style="color: maroon;">"</span><span style="color: #0000e6;">GMT</span><span style="color: maroon;">"</span><span style="color: #808030;">,</span> <span style="color: maroon;">"</span><span style="color: #0000e6;">yyyy-MM-dd</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span><span style="color: purple;">;</span>
<span style="color: maroon;"><strong>var</strong></span> ss <span style="color: #808030;">=</span> SpreadsheetApp<span style="color: #808030;">.</span>getActiveSpreadsheet<span style="color: #808030;">()</span><span style="color: purple;">;</span>
<span style="color: maroon;"><strong>var</strong></span> sheet <span style="color: #808030;">=</span> ss<span style="color: #808030;">.</span>getSheetByName<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #0000e6;">otp-egyenleg</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span><span style="color: purple;">;</span>
sheet<span style="color: #808030;">.</span>appendRow<span style="color: #808030;">([</span>date<span style="color: #808030;">,</span> egyenleg<span style="color: #808030;">])</span><span style="color: purple;">;</span>
<span style="color: purple;">}</span></span></pre>
<br />
<h3>
Még egy kis kiegészítés (aktuális egyenleg)</h3>
<br />
Néha jó lenne rögtön itt látni az aktuális egyenleget (nem csak a tegnap estit).<br />
<br />
Erre csináltam egy függvényt, ami beírja azt egy cellába, és létrehoztam egy trigger-t, ami a doksi megnyitásánál lefuttatja.<br />
<pre style="-webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: white; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px;"><span style="color: maroon;"><strong><span style="font-family: Consolas;">function</span></strong></span><span style="font-family: Consolas;"> updateSpreadWithCurrentBalance<span style="color: #808030;">()</span><span style="color: purple;">{</span>
<span style="color: maroon;"><strong>var</strong></span> ss <span style="color: #808030;">=</span> SpreadsheetApp<span style="color: #808030;">.</span>getActiveSpreadsheet<span style="color: #808030;">()</span><span style="color: purple;">;</span>
<span style="color: maroon;"><strong>var</strong></span> sheet <span style="color: #808030;">=</span> ss<span style="color: #808030;">.</span>getSheetByName<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #0000e6;">otp-egyenleg</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span><span style="color: purple;">;</span>
sheet<span style="color: #808030;">.</span>getRange<span style="color: #808030;">(</span><span style="color: maroon;">"<span style="color: #0000e6;">E2</span></span><span style="color: maroon;">"</span><span style="color: #808030;">).</span>setValue<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #0000e6;">Updating...</span><span style="color: maroon;">"</span><span style="color: #808030;">)</span><span style="color: purple;">;</span>
SpreadsheetApp<span style="color: #808030;">.</span>flush<span style="color: #808030;">()</span><span style="color: purple;">;</span>
<span style="color: maroon;"><strong>var</strong></span> egyenleg <span style="color: #808030;">=</span> getOtpEgyenleg<span style="color: #808030;">()</span><span style="color: purple;">;</span>
sheet<span style="color: #808030;">.</span>getRange<span style="color: #808030;">(</span><span style="color: maroon;">"</span><span style="color: #0000e6;">E2</span><span style="color: maroon;">"</span><span style="color: #808030;">).</span>setValue<span style="color: #808030;">(</span>egyenleg<span style="color: #808030;">)</span><span style="color: purple;">;</span>
<span style="color: purple;">}</span></span></pre>
<br />
…és a trigger:<br />
<br />
<a href="http://lh6.ggpht.com/-wYA50GKTQoE/UAni1-gpdFI/AAAAAAAAIA8/aBkXUfOT6vQ/s1600-h/image9.png"><img alt="image" border="0" src="http://lh3.ggpht.com/-mwBR8m6JCto/UAni2TIQxmI/AAAAAAAAIBI/71nPtrhR-c4/image_thumb4.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" /></a>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2608031287631478389.post-58705622889523208932012-06-20T11:45:00.001+02:002015-06-22T23:25:38.437+02:00TrimageMindig azt mondják, hogy ha tanulni akarunk, akkor szálljunk be valami nyílt-forrású projektbe. Nekem a <a href="https://github.com/Kilian/Trimage" target="_blank">Trimage</a> volt régen egy ilyen projekt. A Trimage alkalmazás <a href="http://kilianvalkhof.com/" target="_blank">Kilian</a> egy aranyos kis Python projektje volt (és valoszleg még ma is az) egyszerű átlátható kóddal.<br />
A Trimage alkalmazás jpeg és png képek veszteségmentes tömörítésére szolgál.<br />
A projektben való részvétel az kb. annyiból állt, hogy commit-olgattam githubon, és Kilian meg lelkesen befogadta őket. Pár e-mailt is váltottunk. Feladatot meg vagy a TODO listáról válaszottam vagy pedig csak úgy találtam valami teendőt.<br />
OOP-sítettem, kicsit átdolgoztam a gui-t, párhuzamosítottam, csináltam windows port-ot és jó pár egyéb apróságot csináltam, és <strong>Kilian egy idő után megtisztelt azzal, hogy a </strong><a href="http://trimage.org/" target="_blank"><strong>projekt weboldalához</strong></a><strong> is </strong><a href="https://github.com/Kilian/Trimage/commit/cbd4d76b6e82f48b58ff19a65ef2a40920a2aaa0#L3R126" target="_blank"><strong>hozzáadta a nevem(commit)</strong></a><strong>. Ezt akkor nagy megtiszteltetésnek éltem meg.</strong><br />
<img src="http://trimage.org/image.png" /> <br />
Biztos vagyok benne, hogy ma is lehetne teendőt találni ezzel kapcsolatban.Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2608031287631478389.post-22796689192874556692012-06-19T23:43:00.000+02:002015-10-06T00:02:54.779+02:00Túl sok időm van labirintusEgyszer el kellett mennem korábban egy <a href="https://www.vik.bme.hu/kepzes/targyak/VIEEA101/" target="_blank">szoftlab1</a> gyakorlatról. Azt akartam, hogy a gyakarlatvezető engedjen el hiányzás beírása nélkül, így hát megdumáltam, hogy következő alkalomra csinálok egy labirintusjátékot, és cserébe elenged hiányzás nélkül.<br />
<br />
Ezen a félvételen épp játszom az alkotásommal:<br />
<img alt="Labirintus" src="http://lh5.ggpht.com/-J-RDOVvyb8I/T-BCV2kdo2I/AAAAAAAAH6k/zF_u4CrkxiY/out_thumb%25255B1%25255D.gif?imgmax=800" style="display: inline;" title="Labirintus" /><br />
<a href="https://gist.github.com/2953373" target="_blank">forrás</a> (fordítás: gcc -o maze maze.c -lncurses)<br />
<br />
Mikor megmutattam neki következő alkalommal, akkor kiderült, hogy nem gondolta komolyan, hogy megcsinálom, és nem is várta el, és <strong>a</strong><span style="background-color: white;"><strong>zt mondta, hogy túl sok időm </strong>van... És ezt negatívan mondta...</span><br />
<br />
<strong>"Képernyőkímélősített" verzió: </strong>(Yep… Unatkoztam labon.)<strong> </strong><br />
<img alt=""Képernyőkímélősített"labirintus" src="http://lh3.ggpht.com/-7eow8i2v2Ck/T-BJ__tPkKI/AAAAAAAAH7c/abYqh2bcBv4/out_metaacity_fast_thumb1.gif?imgmax=800" style="display: inline;" title=""Képernyőkímélősített"labirintus" /><br />
<a href="https://gist.github.com/2953374" target="_blank">forrás</a> (fordítás: gcc –lncurses animatedmaze.c)<br />
<br />
A labirintust <a href="http://en.wikipedia.org/wiki/Maze_generation_algorithm#Depth-first_search" target="_blank">randomizált DFS</a>-el generáltam, ami jól látszik is az animációban. A slow-motion animációban meg még jobban.<br />
Ez egy backtracking algoritmus, ami itt azt jelenti, hogy addig megy a láthatatlan útcsináló mindig véletlen valamerre, amíg tud. Aztán ha elakad, mert már minden irányban út van a fal túloldalán (és két utat nem akarunk egymásba nyitni, mert köröket nem szeretnénk a labirintusba), akkor egész addig visszamegy, amíg már nem ilyen helyen jár, és ott folytatja útcsináló tevékenységét. Ennyi az egész.<br />
<br />
<strong style="background-color: white;">Slow-motion:</strong><br />
<img alt=""Képernyőkímélősített" slow-motion labirintus" src="http://lh4.ggpht.com/-5W7k2GaIsB8/T-BKCIfnV-I/AAAAAAAAH7o/c-ENDbRgw6s/out_metaacity_slow_thumb%25255B1%25255D.gif?imgmax=800" style="display: inline;" title=""Képernyőkímélősített" slow-motion labirintus" /> <br />
Am egész baráti a korábban linkelt c kódom, és a 2 verzió csak pár sorban tér el.<br />
<em>Ui.: El nem tudjátok képzelni, hogy mennyit vacakoltam, mire ilyen csili-vili animált gif-eket tudtam csinálni ebből, szóval szeressétek.</em>Unknownnoreply@blogger.com