<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; AHK v1: Обновить состояние скрипта, скачивающего посты ВК]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=18497</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=18497&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «AHK v1: Обновить состояние скрипта, скачивающего посты ВК».]]></description>
		<lastBuildDate>Thu, 23 Oct 2025 16:03:20 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: AHK v1: Обновить состояние скрипта, скачивающего посты ВК]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=162800#p162800</link>
			<description><![CDATA[<p>У меня каждый раз сообщение:<br /></p><div class="quotebox"><blockquote><p>Извините! Произошла ошибка.<br />Это временная ошибка. Просто обновите страницу. Если проблема не решается, попробуйте повторить через 5-10 минут.</p></blockquote></div><div class="quotebox"><cite>teadrinker пишет:</cite><blockquote><p>Да как-то слишком заморочно ради одного ответа на форуме.</p></blockquote></div><p>Сам код с процедурой и токеном вполне рабочий, если сделать 2 скрипта - где один запускает второй и таким образом сбрасывает какие-то данные, мешающие очередной итерации. Хотелось бы понять, в чем теоретически может быть проблема. То есть, нужно как-то добиться, чтобы на второй итерации скрипт полностью обнулялся, как будто его только что запустили и в этом случае вторая итерация работает.</p>]]></description>
			<author><![CDATA[null@example.com (1srafel)]]></author>
			<pubDate>Thu, 23 Oct 2025 16:03:20 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=162800#p162800</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v1: Обновить состояние скрипта, скачивающего посты ВК]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=162799#p162799</link>
			<description><![CDATA[<div class="quotebox"><cite>1srafel пишет:</cite><blockquote><p>Форум не дает сохранить 3-ю часть.</p></blockquote></div><p>Тестовый код:<br /></p><div class="codebox"><pre><code>#Requires AutoHotkey v2

part1 := [
    {note: &#039;D&#039; , octave: 5, start:    0, duration: 200},
    {note: &#039;D&#039; , octave: 5, start:  600, duration: 200},
    {note: &#039;B&#039; , octave: 4, start: 1200, duration: 400},
    {note: &#039;A#&#039;, octave: 4, start: 1600, duration: 200},
    {note: &#039;B&#039; , octave: 4, start: 1800, duration: 400},
    {note: &#039;C#&#039;, octave: 5, start: 2200, duration: 200},

    {note: &#039;D&#039; , octave: 4, start:    0, duration: 350},
    {note: &#039;F#&#039;, octave: 4, start:    0, duration: 350},
    {note: &#039;G&#039; , octave: 4, start: 1200, duration: 400},
    {note: &#039;D&#039; , octave: 4, start: 1200, duration: 400},
    {note: &#039;F#&#039;, octave: 4, start: 1600, duration: 200},
    {note: &#039;G&#039; , octave: 4, start: 1800, duration: 400},
    {note: &#039;A&#039; , octave: 4, start: 2200, duration: 200},
]

part2 := [
    {note: &#039;D&#039; , octave: 5, start:    0, duration: 200},
    {note: &#039;A&#039; , octave: 4, start:    0, duration: 200},
    {note: &#039;E&#039; , octave: 5, start:  600, duration: 200},
    {note: &#039;C#&#039;, octave: 5, start:  600, duration: 200},
    {note: &#039;F#&#039;, octave: 5, start: 1200, duration: 200},
    {note: &#039;F#&#039;, octave: 5, start: 1800, duration: 200},
    {note: &#039;D&#039; , octave: 5, start: 1800, duration: 200},

    {note: &#039;D&#039; , octave: 4, start:    0, duration: 350},
    {note: &#039;F#&#039;, octave: 4, start:    0, duration: 350},
    {note: &#039;C#&#039;, octave: 5, start:  600, duration: 200},
    {note: &#039;D&#039; , octave: 5, start: 1200, duration: 200}
]

part3 := [
    {note: &#039;G&#039; , octave: 5, start:    0, duration: 400},
    {note: &#039;E&#039; , octave: 5, start:    0, duration: 400},
    {note: &#039;F#&#039;, octave: 5, start:  400, duration: 200},
    {note: &#039;D&#039; , octave: 5, start:  400, duration: 200},
    {note: &#039;E&#039; , octave: 5, start:  600, duration: 400},
    {note: &#039;C#&#039;, octave: 5, start:  600, duration: 400},
    {note: &#039;D&#039; , octave: 5, start: 1000, duration: 200},
    {note: &#039;B&#039; , octave: 4, start: 1000, duration: 200},
    {note: &#039;E&#039; , octave: 5, start: 1200, duration: 200},
    {note: &#039;C#&#039;, octave: 5, start: 1200, duration: 200},
    {note: &#039;A&#039; , octave: 4, start: 1550, duration: 100},
    {note: &#039;A&#039; , octave: 4, start: 1670, duration: 100},
    {note: &#039;A&#039; , octave: 4, start: 1800, duration: 200},
    {note: &#039;A&#039; , octave: 4, start: 2100, duration: 200},

    {note: &#039;D&#039; , octave: 4, start:    0, duration: 990},
    {note: &#039;A&#039; , octave: 4, start:    0, duration: 990},
    {note: &#039;A&#039; , octave: 3, start: 1200, duration: 400}
]

part4 := [
    {note: &#039;E&#039; , octave: 5, start:    0, duration: 400},
    {note: &#039;C#&#039;, octave: 5, start:    0, duration: 400},
    {note: &#039;D&#039;,  octave: 5, start:  400, duration: 200},
    {note: &#039;B&#039;,  octave: 4, start:  400, duration: 200},
    {note: &#039;C#&#039;, octave: 4, start:  600, duration: 400},
    {note: &#039;A&#039;,  octave: 4, start:  600, duration: 400},
    {note: &#039;B&#039; , octave: 4, start: 1000, duration: 200},
    {note: &#039;G#&#039;, octave: 4, start: 1000, duration: 200},
    {note: &#039;A&#039; , octave: 4, start: 1200, duration: 200},

    {note: &#039;E&#039; , octave: 4, start:    0, duration: 990},
    {note: &#039;A&#039; , octave: 3, start: 1200, duration: 200},
    {note: &#039;A&#039; , octave: 3, start: 1550, duration: 100},
    {note: &#039;A&#039; , octave: 3, start: 1670, duration: 100},
    {note: &#039;A&#039; , octave: 3, start: 1800, duration: 200},
    {note: &#039;A&#039; , octave: 3, start: 2100, duration: 200}
]

part5 := [
    {note: &#039;A&#039; , octave: 4, start:    0, duration: 200},
    {note: &#039;E&#039; , octave: 4, start:    0, duration: 200},
    {note: &#039;A&#039; , octave: 4, start:  600, duration: 200},
    {note: &#039;Bb&#039;, octave: 4, start: 1200, duration: 400},
    {note: &#039;A&#039; , octave: 4, start: 1600, duration: 200},
    {note: &#039;Bb&#039;, octave: 4, start: 1800, duration: 400},
    {note: &#039;G#&#039;, octave: 4, start: 2200, duration: 200},

    {note: &#039;C#&#039;, octave: 4, start:    0, duration: 200},
    {note: &#039;A&#039; , octave: 3, start:    0, duration: 200},
    {note: &#039;F#&#039;, octave: 3, start: 1200, duration: 990},
    {note: &#039;D&#039; , octave: 3, start: 1200, duration: 990}
]

part6 := [
    {note: &#039;A&#039; , octave: 4, start:    0, duration: 200},
    {note: &#039;B&#039; , octave: 4, start:  600, duration: 200},
    {note: &#039;G#&#039;, octave: 4, start: 1200, duration: 200},
    {note: &#039;C#&#039;, octave: 5, start: 1200, duration: 200},
    {note: &#039;A&#039; , octave: 4, start: 1800, duration: 200},
    {note: &#039;C#&#039;, octave: 5, start: 1800, duration: 200},

    {note: &#039;C#&#039;, octave: 4, start:    0, duration: 200},
    {note: &#039;A&#039; , octave: 3, start:    0, duration: 200},
    {note: &#039;E&#039; , octave: 4, start:  600, duration: 200},
    {note: &#039;G#&#039;, octave: 4, start:  600, duration: 200},
    {note: &#039;C#&#039;, octave: 4, start: 1200, duration: 200},
    {note: &#039;F&#039; , octave: 4, start: 1200, duration: 200},
    {note: &#039;F#&#039;, octave: 4, start: 1800, duration: 200}
]

part7 := [
    {note: &#039;B&#039; , octave: 4, start:    0, duration: 400},
    {note: &#039;D&#039; , octave: 5, start:    0, duration: 400},
    {note: &#039;C#&#039;, octave: 5, start:  400, duration: 200},
    {note: &#039;B&#039; , octave: 4, start:  600, duration: 400},
    {note: &#039;A&#039; , octave: 4, start: 1000, duration: 200},
    {note: &#039;G#&#039;, octave: 4, start: 1200, duration: 400},

    {note: &#039;B&#039; , octave: 3, start:    0, duration: 400},
    {note: &#039;F#&#039;, octave: 4, start:    0, duration: 400},
    {note: &#039;E&#039; , octave: 4, start: 1200, duration: 400},
    {note: &#039;D&#039; , octave: 4, start: 1600, duration: 200},
    {note: &#039;C#&#039;, octave: 4, start: 1800, duration: 400},
    {note: &#039;B&#039; , octave: 3, start: 2200, duration: 200},
]

part8 := [
    {note: &#039;B&#039; , octave: 4, start:    0, duration: 400},
    {note: &#039;D&#039; , octave: 5, start:    0, duration: 400},
    {note: &#039;C#&#039;, octave: 5, start:  400, duration: 200},
    {note: &#039;B&#039; , octave: 4, start:  600, duration: 400},
    {note: &#039;C#&#039;, octave: 5, start: 1000, duration: 200},
    {note: &#039;A&#039; , octave: 4, start: 1200, duration: 400},

    {note: &#039;B&#039; , octave: 3, start:    0, duration: 200},
    {note: &#039;F#&#039;, octave: 4, start:    0, duration: 200},
    {note: &#039;E&#039; , octave: 4, start:  600, duration: 200},
    {note: &#039;G#&#039;, octave: 4, start:  600, duration: 200},
    {note: &#039;A&#039; , octave: 3, start: 1200, duration: 400},
    {note: &#039;A&#039; , octave: 3, start: 1600, duration: 200},
    {note: &#039;B&#039; , octave: 3, start: 1800, duration: 400},
    {note: &#039;C#&#039;, octave: 4, start: 2200, duration: 200},
]

part9 := [
    {note: &#039;E&#039; , octave: 5, start:    0, duration: 400},
    {note: &#039;D#&#039;, octave: 5, start:  400, duration: 200},
    {note: &#039;E&#039; , octave: 5, start:  600, duration: 400},
    {note: &#039;F#&#039;, octave: 5, start: 1000, duration: 200},
    {note: &#039;D&#039; , octave: 5, start: 1200, duration: 400},

    {note: &#039;G&#039; , octave: 4, start:    0, duration: 200},
    {note: &#039;B&#039; , octave: 4, start:    0, duration: 200},
    {note: &#039;A&#039; , octave: 4, start:  600, duration: 200},
    {note: &#039;C#&#039;, octave: 5, start:  600, duration: 200},
    {note: &#039;D&#039; , octave: 4, start: 1200, duration: 400}
]

parts := [
    &#039;1&#039;, &#039;1&#039;, &#039;2&#039;, &#039;3&#039;, &#039;1&#039;, &#039;1&#039;, &#039;2&#039;, &#039;4&#039;,
    &#039;5&#039;, &#039;5&#039;, &#039;6&#039;, &#039;7&#039;, &#039;5&#039;, &#039;5&#039;, &#039;6&#039;, &#039;8&#039;,
    &#039;1&#039;, &#039;1&#039;, &#039;2&#039;, &#039;3&#039;, &#039;1&#039;, &#039;1&#039;, &#039;2&#039;, &#039;9&#039;
]

notes := []
for i, n in parts {
    AddPart(notes, part%n%, 2400, i - 1)
}

PlayNotes(notes, 0x7000)

AddPart(notes, part, len, offset) {
    for item in part {
        newItem := item.Clone()
        newItem.start += len * offset
        notes.Push(newItem)
    }
}

ShowGui() {
    wnd := Gui(&#039;AlwaysOnTop -Caption Owner&#039;)
    wnd.BackColor := 0xC8BA8D
    wnd.MarginX := wnd.MarginY := 25
    wnd.SetFont(&#039;s18 c0x6A688C&#039;, &#039;Calibri&#039;)
    wnd.AddText(, &#039;The buffer is being formed, this may take a few seconds...&#039;)
    wnd.Show()
    return wnd
}

PlayNotes(notes, amp := 0x7FFF, attackMs := 5, decayMs := 30,
          sustainLevel := 0.7, releaseMs := 100, sampleRate := 48000) {
    wnd := ShowGui()
    buf := GeneratePolyphonicBuffer(notes, sampleRate, amp, attackMs, decayMs, sustainLevel, releaseMs)
    wnd.Destroy()
    PlayBuffer(buf, sampleRate)
}

CreateNoteMap(startOctave := 0, endOctave := 8) {
    noteMap := Map()
    notes := [&#039;C&#039;, [&#039;C#&#039;,&#039;Db&#039;], &#039;D&#039;, [&#039;D#&#039;,&#039;Eb&#039;], &#039;E&#039;, &#039;F&#039;, 
              [&#039;F#&#039;,&#039;Gb&#039;], &#039;G&#039;, [&#039;G#&#039;,&#039;Ab&#039;], &#039;A&#039;, [&#039;A#&#039;,&#039;Bb&#039;], &#039;B&#039;]
    
    A4_freq := 440
    A4_semitone := 57  ; A4 = 4×12 + 9
    
    Loop (endOctave - startOctave + 1) {
        octave := startOctave + A_Index - 1
        Loop 12 {
            noteIndex := A_Index - 1
            semitone := octave * 12 + noteIndex
            freq := A4_freq * (2 ** ((semitone - A4_semitone) / 12))
            
            note := notes[noteIndex + 1]
            if note is Array {
                noteMap[note[1] . octave] := freq  ; sharp
                noteMap[note[2] . octave] := freq  ; flat
            } else {
                noteMap[note . octave] := freq
            }
        }
    }
    return noteMap
}

GeneratePolyphonicBuffer(notes, sampleRate := 48000, amp := 20000, 
                         attackMs := 10, decayMs := 50, sustainLevel := 0.7, releaseMs := 100) {
    static noteMap := CreateNoteMap(0, 8), twoPi := 2 * ACos(-1)
    
    totalDuration := 0
    for note in notes {
        endTime := note.start + note.duration
        if endTime &gt; totalDuration {
            totalDuration := endTime
        }
    }
    
    if totalDuration = 0 {
        return Buffer(0)
    }
    
    totalSamples := Round(sampleRate * totalDuration / 1000)
    floatBuf := Buffer(totalSamples * 8, 0)
    attackSamples  := Round(sampleRate * attackMs  / 1000)
    decaySamples   := Round(sampleRate * decayMs   / 1000)
    releaseSamples := Round(sampleRate * releaseMs / 1000)
    
    for note in notes {
        noteName := note.note . note.octave
        if !noteMap.Has(noteName) {
            throw Error(&#039;Unknown note: &#039; . noteName)
        }
        
        freq := noteMap[noteName]
        startSample := Round(sampleRate * note.start / 1000)
        noteSamples := Round(sampleRate * note.duration / 1000)
        
        phaseInc := twoPi * freq / sampleRate
        phase := 0.0
        
        Loop noteSamples {
            i := A_Index - 1
            globalIndex := startSample + i
            
            if globalIndex &gt;= totalSamples {
                break
            }
            
            sample := Sin(phase) * amp
            phase += phaseInc
            
            if i &lt; attackSamples {
                sample *= i / attackSamples
            } else if i &lt; attackSamples + decaySamples {
                decayProgress := (i - attackSamples) / decaySamples
                sample *= 1 - (1 - sustainLevel) * decayProgress
            } else if i &lt; noteSamples - releaseSamples {
                sample *= sustainLevel
            } else {
                releaseProgress := (i - (noteSamples - releaseSamples)) / releaseSamples
                sample *= sustainLevel * (1 - releaseProgress)
            }
            
            offset := globalIndex * 8
            currentVal := NumGet(floatBuf, offset, &#039;Double&#039;)
            NumPut(&#039;Double&#039;, currentVal + sample, floatBuf, offset)
        }
    }
    
    ; normalization
    maxAmp := 0.0
    Loop totalSamples {
        absVal := Abs(NumGet(floatBuf, (A_Index - 1) * 8, &#039;Double&#039;))
        if absVal &gt; maxAmp {
            maxAmp := absVal
        }
    }
    
    scale := (maxAmp &gt; 32767) ? (32767 / maxAmp) : 1.0
    
    ; converting to int16 PCM
    buf := Buffer(totalSamples * 2, 0)
    Loop totalSamples {
        value := Round(NumGet(floatBuf, (A_Index - 1) * 8, &#039;Double&#039;) * scale)
        NumPut(&#039;Short&#039;, value, buf, (A_Index - 1) * 2)
    }
    
    return buf
}

PlayBuffer(buf, sampleRate := 48000, channels := 1) {
    static WAVE_FORMAT_PCM := 1, WHDR_DONE := 0x00000001, bytesPerSample := 2
    if buf.Size = 0 {
        return
    }
    blockAlign := channels * bytesPerSample
    avgBytesPerSec := sampleRate * blockAlign

    WAVEFORMATEX := Buffer(18, 0)
    NumPut(&#039;UShort&#039;, WAVE_FORMAT_PCM, &#039;UShort&#039;, channels,
           &#039;UInt&#039;  , sampleRate     , &#039;UInt&#039;  , avgBytesPerSec,
           &#039;UShort&#039;, blockAlign     , &#039;UShort&#039;, bytesPerSample * 8, WAVEFORMATEX)
    r := DllCall(&#039;winmm\waveOutOpen&#039;, &#039;Ptr*&#039;, &amp;hWaveOut := 0, &#039;UInt&#039;, 0xFFFFFFFF, &#039;Ptr&#039;, WAVEFORMATEX, &#039;Ptr&#039;, 0, &#039;Ptr&#039;, 0, &#039;UInt&#039;, 0)
    if r != 0 {
        throw Error(&#039;waveOutOpen failed: &#039; . r)
    }

    WAVEHDR := Buffer(A_PtrSize = 8 ? 48 : 32, 0)
    NumPut(&#039;Ptr&#039;, buf.ptr, &#039;UInt&#039;, buf.size, WAVEHDR)
    DllCall(&#039;winmm\waveOutPrepareHeader&#039;, &#039;Ptr&#039;, hWaveOut, &#039;Ptr&#039;, WAVEHDR, &#039;UInt&#039;, WAVEHDR.size)
    DllCall(&#039;winmm\waveOutWrite&#039;, &#039;Ptr&#039;, hWaveOut, &#039;Ptr&#039;, WAVEHDR, &#039;UInt&#039;, WAVEHDR.size)

    Loop {
        Sleep 100
    } until NumGet(WAVEHDR, A_PtrSize * 2 + 8, &#039;UInt&#039;) &amp; WHDR_DONE

    DllCall(&#039;winmm\waveOutUnprepareHeader&#039;, &#039;Ptr&#039;, hWaveOut, &#039;Ptr&#039;, WAVEHDR, &#039;UInt&#039;, WAVEHDR.size)
    DllCall(&#039;winmm\waveOutClose&#039;, &#039;Ptr&#039;, hWaveOut)
}</code></pre></div><p>У меня всё вроде работает, никаких проблем.<br /></p><div class="quotebox"><cite>1srafel пишет:</cite><blockquote><p>Для запроса используется приведенная &quot;хранимая процедура&quot;, которую нужно создать на сайте - и токен</p></blockquote></div><p>Да как-то слишком заморочно ради одного ответа на форуме. Я бы платно взялся.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Thu, 23 Oct 2025 11:22:38 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=162799#p162799</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v1: Обновить состояние скрипта, скачивающего посты ВК]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=162798#p162798</link>
			<description><![CDATA[<p>Форум не дает сохранить 3-ю часть.</p>]]></description>
			<author><![CDATA[null@example.com (1srafel)]]></author>
			<pubDate>Thu, 23 Oct 2025 10:16:44 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=162798#p162798</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v1: Обновить состояние скрипта, скачивающего посты ВК]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=162793#p162793</link>
			<description><![CDATA[<p><strong>AHK v1<br />(Третья часть кода)</strong></p><p>&nbsp; &nbsp; ; Документы<br />&nbsp; &nbsp; if (post.documents.MaxIndex() &gt; 0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; html .= &quot;&nbsp; &nbsp; &lt;div class=&#039;media-attachments&#039;&gt;`n&quot;<br />&nbsp; &nbsp; &nbsp; &nbsp; html .= &quot;&nbsp; &nbsp; &nbsp; &nbsp; &lt;div class=&#039;section-title&#039;&gt;[Документы: &quot; post.documents.MaxIndex() &quot;]&lt;/div&gt;`n&quot;<br />&nbsp; &nbsp; &nbsp; &nbsp; for index, doc_data in post.documents {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; html .= &quot;&nbsp; &nbsp; &nbsp; &nbsp; &lt;div class=&#039;document-attachment&#039;&gt;`n&quot;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; html .= &quot;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;div class=&#039;document-icon&#039;&gt;</p>]]></description>
			<author><![CDATA[null@example.com (1srafel)]]></author>
			<pubDate>Thu, 23 Oct 2025 02:37:56 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=162793#p162793</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v1: Обновить состояние скрипта, скачивающего посты ВК]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=162792#p162792</link>
			<description><![CDATA[<p><strong>AHK v1<br />(Вторая часть кода)</strong></p><div class="codebox"><pre><code>; Получение самой большой фотографии
GetLargestPhotoUrl(photo) {
    if (!photo.sizes || photo.sizes.Length() = 0) {
        return &quot;&quot;
    }
    
    ; Сортируем размеры по ширине (от большего к меньшему)
    largest_size := &quot;&quot;
    largest_width := 0
    
    for index, size in photo.sizes {
        if (size.width &gt; largest_width) {
            largest_width := size.width
            largest_size := size
        }
    }
    
    return largest_size ? largest_size.url : &quot;&quot;
}

; Конвертация поста в HTML
ConvertPostToHTML(post) {
    html := &quot;&quot;
    html .= &quot;&lt;!DOCTYPE html&gt;`n&quot;
    html .= &quot;&lt;html lang=&#039;ru&#039;&gt;`n&quot;
    html .= &quot;&lt;head&gt;`n&quot;
    html .= &quot;    &lt;meta charset=&#039;UTF-8&#039;&gt;`n&quot;
    html .= &quot;    &lt;meta name=&#039;viewport&#039; content=&#039;width=device-width, initial-scale=1.0&#039;&gt;`n&quot;
    
    ; 1) Используем title из JSON как заголовок поста
    post_title := post.title ? EscapeHTML(post.title) : &quot;Пост &quot; post.id &quot; из &quot; post.owner_id
    html .= &quot;    &lt;title&gt;&quot; post_title &quot;&lt;/title&gt;`n&quot;
    
    html .= &quot;    &lt;style&gt;`n&quot;
    html .= &quot;        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; background: #f5f5f5; }`n&quot;
    html .= &quot;        .post { background: white; border-radius: 12px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }`n&quot;
    html .= &quot;        .post-header { display: flex; align-items: center; justify-content: space-between; color: #666; font-size: 14px; margin-bottom: 15px; }`n&quot;
    html .= &quot;        .post-header-info { display: flex; align-items: center; flex-grow: 1; }`n&quot;
    html .= &quot;        .avatar { width: 40px; height: 40px; border-radius: 50%; margin-right: 10px; vertical-align: middle; border: 1px solid #e1e3e6; }`n&quot;
    html .= &quot;        .date { color: #2a5885; text-decoration: none; font-weight: bold; }`n&quot;
    html .= &quot;        .date:hover { text-decoration: underline; }`n&quot;
    html .= &quot;        .post-title { font-size: 20px; font-weight: bold; margin-bottom: 15px; color: #000; border-bottom: 2px solid #2a5885; padding-bottom: 10px; }`n&quot;
    html .= &quot;        .media-attachments { margin-bottom: 15px; }`n&quot;
    html .= &quot;        .media-attachment { margin-bottom: 10px; }`n&quot;
    html .= &quot;        .my { max-width: 100%; height: auto; border-radius: 8px; display: block; }`n&quot;
    html .= &quot;        .post-text { font-size: 16px; line-height: 1.5; margin-bottom: 15px; white-space: pre-wrap; }`n&quot;
    html .= &quot;        .post-stats { color: #666; font-size: 14px; margin-bottom: 15px; padding-top: 15px; border-top: 1px solid #eee; }`n&quot;
    html .= &quot;        .group-name { color: #2a5885; font-weight: bold; }`n&quot;
    html .= &quot;        .link-attachment { border: 1px solid #e1e3e6; border-radius: 8px; padding: 12px; margin-bottom: 10px; display: flex; align-items: center; }`n&quot;
    html .= &quot;        .link-preview { width: 80px; height: 80px; border-radius: 4px; margin-right: 12px; object-fit: cover; }`n&quot;
    html .= &quot;        .link-info { flex: 1; }`n&quot;
    html .= &quot;        .link-title { font-weight: bold; margin-bottom: 4px; }`n&quot;
    html .= &quot;        .link-description { color: #666; font-size: 14px; margin-bottom: 4px; }`n&quot;
    html .= &quot;        .link-url { color: #2a5885; font-size: 12px; }`n&quot;
    html .= &quot;        .section-title { font-size: 16px; font-weight: bold; margin: 15px 0 10px 0; color: #aaaaaa; }`n&quot;
    html .= &quot;        .media-info { color: #666; font-size: 14px; margin-top: 5px; }`n&quot;
    html .= &quot;        .document-attachment { border: 1px solid #e1e3e6; border-radius: 8px; padding: 12px; margin-bottom: 10px; display: flex; align-items: center; }`n&quot;
    html .= &quot;        .document-icon { width: 48px; height: 48px; margin-right: 12px; background: #f0f0f0; border-radius: 4px; display: flex; align-items: center; justify-content: center; font-size: 24px; }`n&quot;
    html .= &quot;        .document-info { flex: 1; }`n&quot;
    html .= &quot;        .document-title { font-weight: bold; margin-bottom: 4px; }`n&quot;
    html .= &quot;        .document-details { color: #666; font-size: 12px; }`n&quot;
    html .= &quot;        .poll-attachment { border: 1px solid #e1e3e6; border-radius: 8px; padding: 12px; margin-bottom: 10px; }`n&quot;
    html .= &quot;        .poll-question { font-weight: bold; margin-bottom: 10px; }`n&quot;
    html .= &quot;        .poll-answer { margin-bottom: 5px; padding: 5px; background: #f9f9f9; border-radius: 4px; }`n&quot;
    html .= &quot;        .poll-votes { color: #666; font-size: 12px; margin-top: 5px; }`n&quot;
    html .= &quot;        .poll-properties { margin-bottom: 10px; padding: 8px; background: #f0f8ff; border-radius: 6px; font-size: 12px; }`n&quot;
    html .= &quot;        .poll-property { display: inline-block; margin-right: 10px; margin-bottom: 5px; padding: 3px 8px; background: white; border-radius: 12px; border: 1px solid #d4e6ff; }`n&quot;
    html .= &quot;        .poll-stats { color: #666; font-size: 12px; margin-top: 8px; }`n&quot;
    html .= &quot;        .repost-attachment { border: 1px solid #e1e3e6; border-radius: 8px; padding: 12px; margin-bottom: 10px; background: #f9f9f9; }`n&quot;
    html .= &quot;        .album-attachment { border: 1px solid #e1e3e6; border-radius: 8px; padding: 12px; margin-bottom: 10px; display: flex; align-items: center; }`n&quot;
    html .= &quot;        .album-icon { width: 48px; height: 48px; margin-right: 12px; background: #f0f0f0; border-radius: 4px; display: flex; align-items: center; justify-content: center; font-size: 24px; }`n&quot;
    html .= &quot;        .album-info { flex: 1; }`n&quot;
    html .= &quot;        .album-title { font-weight: bold; margin-bottom: 4px; }`n&quot;
    html .= &quot;        .album-details { color: #666; font-size: 12px; }`n&quot;
    html .= &quot;        a { color: #2a5885; text-decoration: none; }`n&quot;
    html .= &quot;        a:hover { text-decoration: underline; }`n&quot;
    html .= &quot;        .text-link { color: #2a5885; text-decoration: none; }`n&quot;
    html .= &quot;        .text-link:hover { text-decoration: underline; }`n&quot;
    html .= &quot;        .mention { color: #2a5885; text-decoration: none; }`n&quot;
    html .= &quot;        .mention:hover { text-decoration: underline; }`n&quot;
    html .= &quot;    &lt;/style&gt;`n&quot;
    html .= &quot;&lt;/head&gt;`n&quot;
    html .= &quot;&lt;body&gt;`n&quot;
    
    ; Пост
    html .= &quot;&lt;div class=&#039;post&#039;&gt;`n&quot;
    
    ; 1) Заголовок поста (если есть в JSON) - содержимое &quot;title&quot; попадает сюда
    if (post.title != &quot;&quot;) {
        html .= &quot;    &lt;h1 class=&#039;post-title&#039;&gt;&quot; EscapeHTML(post.title) &quot;&lt;/h1&gt;`n&quot;
    }
    
    ; Заголовок поста с информацией о группе
    html .= &quot;    &lt;div class=&#039;post-header&#039;&gt;`n&quot;
    
    ; Определяем аватар (группы или пользователя)
    avatar_url := &quot;&quot;
    if (post.group_avatar != &quot;&quot;) {
        avatar_url := post.group_avatar
    } else if (post.user_avatar != &quot;&quot;) {
        avatar_url := post.user_avatar
    }
    
    ; Отображаем аватар и информацию
    html .= &quot;        &lt;div class=&#039;post-header-info&#039;&gt;`n&quot;
    if (avatar_url != &quot;&quot;) {
        html .= &quot;            &lt;img class=&#039;avatar&#039; src=&#039;&quot; avatar_url &quot;&#039; alt=&#039;Аватар&#039;&gt;`n&quot;
    }
    
    ; 2) Название группы оборачиваем в ссылку из screen_name
    if (post.group_screen_name != &quot;&quot;) {
        html .= &quot;            &lt;a class=&#039;group-name&#039; href=&#039;https://vk.com/&quot; post.group_screen_name &quot;&#039; target=&#039;_blank&#039;&gt;&quot; EscapeHTML(post.group_name) &quot;&lt;/a&gt;`n&quot;
    } else {
        html .= &quot;            &lt;span class=&#039;group-name&#039;&gt;&quot; EscapeHTML(post.group_name) &quot;&lt;/span&gt;`n&quot;
    }
    html .= &quot;        &lt;/div&gt;`n&quot;
    
    html .= &quot;        &lt;a class=&#039;date&#039; href=&#039;https://vk.com/wall&quot; post.owner_id &quot;_&quot; post.id &quot;&#039; target=&#039;_blank&#039;&gt;&quot; FormatTimestampHTML(post.date) &quot;&lt;/a&gt;`n&quot;
    html .= &quot;    &lt;/div&gt;`n&quot;
    
    ; Фото
    if (post.photos.MaxIndex() &gt; 0) {
        html .= &quot;    &lt;div class=&#039;media-attachments&#039;&gt;`n&quot;
        for index, photo_url in post.photos {
            html .= &quot;        &lt;div class=&#039;media-attachment&#039;&gt;`n&quot;
            html .= &quot;            &lt;a href=&#039;&quot; photo_url &quot;&#039; target=&#039;_blank&#039;&gt;&lt;img class=&#039;my&#039; src=&#039;&quot; photo_url &quot;&#039; alt=&#039;Фото&#039;&gt;&lt;/a&gt;`n&quot;
            html .= &quot;        &lt;/div&gt;`n&quot;
        }
        html .= &quot;    &lt;/div&gt;`n&quot;
    }
    
    ; Ссылки
    if (post.links.MaxIndex() &gt; 0) {
        html .= &quot;    &lt;div class=&#039;media-attachments&#039;&gt;`n&quot;
        for index, link_data in post.links {
            html .= &quot;        &lt;div class=&#039;link-attachment&#039;&gt;`n&quot;
            if (link_data.preview_url != &quot;&quot;) {
                html .= &quot;            &lt;img class=&#039;link-preview&#039; src=&#039;&quot; link_data.preview_url &quot;&#039; alt=&#039;Превью&#039;&gt;`n&quot;
            }
            html .= &quot;            &lt;div class=&#039;link-info&#039;&gt;`n&quot;
            if (link_data.title != &quot;&quot;) {
                html .= &quot;                &lt;div class=&#039;link-title&#039;&gt;&lt;a href=&#039;&quot; link_data.url &quot;&#039; target=&#039;_blank&#039;&gt;&quot; EscapeHTML(link_data.title) &quot;&lt;/a&gt;&lt;/div&gt;`n&quot;
            }
            if (link_data.description != &quot;&quot;) {
                html .= &quot;                &lt;div class=&#039;link-description&#039;&gt;&quot; EscapeHTML(link_data.description) &quot;&lt;/div&gt;`n&quot;
            }
            html .= &quot;                &lt;div class=&#039;link-url&#039;&gt;&quot; link_data.url &quot;&lt;/div&gt;`n&quot;
            html .= &quot;            &lt;/div&gt;`n&quot;
            html .= &quot;        &lt;/div&gt;`n&quot;
        }
        html .= &quot;    &lt;/div&gt;`n&quot;
    }
    
    ; Видео
    if (post.videos.MaxIndex() &gt; 0) {
        html .= &quot;    &lt;div class=&#039;media-attachments&#039;&gt;`n&quot;
        html .= &quot;        &lt;div class=&#039;section-title&#039;&gt;[Видео: &quot; post.videos.MaxIndex() &quot;]&lt;/div&gt;`n&quot;
        for index, video_data in post.videos {
            html .= &quot;        &lt;div class=&#039;media-attachment&#039;&gt;`n&quot;
            if (video_data.preview_url != &quot;&quot;) {
                html .= &quot;            &lt;a href=&#039;https://vk.com/video&quot; video_data.owner_id &quot;_&quot; video_data.id &quot;&#039; target=&#039;_blank&#039;&gt;&lt;img class=&#039;my&#039; src=&#039;&quot; video_data.preview_url &quot;&#039; alt=&#039;Видео&#039;&gt;&lt;/a&gt;`n&quot;
            }
            html .= &quot;            &lt;div class=&#039;media-info&#039;&gt;`n&quot;
            if (video_data.duration &gt; 0) {
                html .= &quot;                Длительность: &quot; FormatDuration(video_data.duration) &quot;`n&quot;
            }
            html .= &quot;            &lt;/div&gt;`n&quot;
            html .= &quot;            &lt;h3&gt;&quot; EscapeHTML(video_data.title) &quot;&lt;/h3&gt;`n&quot;
            html .= &quot;        &lt;/div&gt;`n&quot;
        }
        html .= &quot;    &lt;/div&gt;`n&quot;
    }
    
    ; Аудио
    if (post.audios.MaxIndex() &gt; 0) {
        html .= &quot;    &lt;div class=&#039;media-attachments&#039;&gt;`n&quot;
        html .= &quot;        &lt;div class=&#039;section-title&#039;&gt;[Аудио: &quot; post.audios.MaxIndex() &quot;]&lt;/div&gt;`n&quot;
        for index, audio_data in post.audios {
            html .= &quot;        &lt;div class=&#039;media-attachment&#039;&gt;`n&quot;
            html .= &quot;            &lt;div&gt;&lt;strong&gt;&quot; EscapeHTML(audio_data.artist) &quot; - &quot; EscapeHTML(audio_data.title) &quot;&lt;/strong&gt;&lt;/div&gt;`n&quot;
            html .= &quot;            &lt;div class=&#039;media-info&#039;&gt;Длительность: &quot; FormatDuration(audio_data.duration) &quot;&lt;/div&gt;`n&quot;
            html .= &quot;        &lt;/div&gt;`n&quot;
        }
        html .= &quot;    &lt;/div&gt;`n&quot;
    }
</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (1srafel)]]></author>
			<pubDate>Thu, 23 Oct 2025 02:36:43 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=162792#p162792</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK v1: Обновить состояние скрипта, скачивающего посты ВК]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=162791#p162791</link>
			<description><![CDATA[<p>Только сейчас увидел, что надублировал тем. Извиняюсь. Связано это с тем, что после каждой попытки опубликовать тему, всплывало сообщение об ошибке и предложение попробовать через 5-10 минут. Видимо, из-за большого размера скрипта.</p>]]></description>
			<author><![CDATA[null@example.com (1srafel)]]></author>
			<pubDate>Thu, 23 Oct 2025 02:33:54 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=162791#p162791</guid>
		</item>
		<item>
			<title><![CDATA[AHK v1: Обновить состояние скрипта, скачивающего посты ВК]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=162776#p162776</link>
			<description><![CDATA[<p>Составил с ИИ код ниже, который за 1 запрос может скачивать до 100 постов из VK с форматированием в HTML-формат различных типов ВК-постов. Для запроса используется приведенная &quot;хранимая процедура&quot;, которую нужно создать на сайте - и токен, прописываемый в файл &quot;token.txt&quot;. Так же используется библиотека <a href="https://github.com/cocobelgica/AutoHotkey-JSON/blob/master/JSON.ahk">JSON.ahk</a>.</p><p>Код имеет странную проблему, когда после парсинга json-ответа первой итерации (offset := 0), на второй итерации (offset := 1) json-ответ не распознается как валидный. При этом достоверно известно, что все последующие ответы валидны, что проверялось подменой ответа первой итерации - ответом второй итерации, а так же при старте скрипта - запуском парсинга со второй итерации. Пытался очищать предыдущее состояние всех данных, но помогает только перезагрузка скрипта, когда JSON класс полностью обновляется. Просьба подсказать решение задачи с полным обновлением состояния скрипта после каждой итерации.</p><p><strong>Хранимая процедура</strong></p><div class="codebox"><pre><code>// execute.getMaxPosts
var response = API.wall.get({
    &quot;owner_id&quot;: Args.owner_id,
    &quot;offset&quot;: Args.offset,
    &quot;count&quot;: 25,  // 100 — МАКСИМУМ ДЛЯ WALL.GET
    &quot;extended&quot;: 1,
    &quot;fields&quot;: &quot;first_name,last_name&quot;,
    &quot;v&quot;: &quot;5.291&quot;
});

return response;</code></pre></div><p><strong>AHK v1<br />(Первая часть кода)</strong></p><br /><div class="codebox"><pre><code>#NoEnv
SendMode Input
#SingleInstance Force
SetWorkingDir %A_ScriptDir%

; Подключаем JSON.ahk
#Include JSON.ahk

; Чтение токена из файла
FileRead, access_token, token.txt
if (ErrorLevel || access_token = &quot;&quot;) {
    MsgBox, Не удалось прочитать токен из файла token.txt
    ExitApp
}

; Убираем возможные пробелы и переводы строк
access_token := Trim(access_token)

owner_id := &quot;-29534144&quot;
output_folder := &quot;VK_Posts_HTML&quot;

; Создаем папку для сохранения
FileCreateDir, %output_folder%

; Получаем и сохраняем все посты
total_posts := GetAllPostsAndSaveHTML(access_token, owner_id, output_folder)
MsgBox, % &quot;Готово! Сохранено постов: &quot; total_posts

; Основная функция для получения всех постов
GetAllPostsAndSaveHTML(access_token, owner_id, output_folder) {
    total_saved := 0
    batch_size := 25
    offset := 0
    total_count := 0  ; Добавляем переменную для общего количества постов
    
    Loop {
        ; Получаем пачку постов через execute
        posts_data := GetPostsBatch(access_token, owner_id, offset)
        if (!posts_data || !posts_data.items || posts_data.items.MaxIndex() = 0) {
            break
        }
        
        ; Сохраняем общее количество постов при первом запросе
        if (offset = 0 &amp;&amp; posts_data.count &gt; 0) {
            total_count := posts_data.count
        }
        
        ; Обрабатываем каждый пост
        for index, post_item in posts_data.items {
            ; Парсим пост в наш формат
            post_data := ParsePostItem(post_item, posts_data)
            if (post_data &amp;&amp; post_data.id) {
                html_content := ConvertPostToHTML(post_data)
                filename := output_folder &quot;\&quot; owner_id &quot;_&quot; post_data.id &quot;.html&quot;
                SaveHTMLToFile(html_content, filename)
                total_saved++
                
                ; Прогресс с информацией об общем количестве
                progress_text := &quot;Сохранено: &quot; total_saved &quot; из &quot; total_count &quot; постов (offset: &quot; offset &quot;)&quot;
                if (total_count &gt; 0) {
                    percent := Round((total_saved / total_count) * 100)
                    progress_text .= &quot; (&quot; percent &quot;%)&quot;
                }
                ToolTip, % progress_text
            }
        }
        
        offset += batch_size ; Увеличиваем offset для следующей пачки
        Sleep, 2500  ; Пауза между запросами
        
        ; если сохранили больше или равно общему количеству постов - выходим
        if (total_count &gt; 0 &amp;&amp; total_saved &gt;= total_count) {
            break
        }
        
        ; Дополнительная проверка: если в ответе нет постов
        if (posts_data.items.MaxIndex() = 0) {
            break
        }
    }
    
    ToolTip
    return total_saved
}

; Получение пачки постов через execute.getMaxPosts
GetPostsBatch(access_token, owner_id, offset) {
    url := &quot;https://api.vk.com/method/execute.getMaxPosts?owner_id=&quot; owner_id
        . &quot;&amp;offset=&quot; offset
        . &quot;&amp;access_token=&quot; access_token
        . &quot;&amp;v=5.291&quot;
    
    response := SendHTTPRequest(url)
    
    ; Сохраняем сырой ответ для отладки
    FileDelete, debug_batch_%offset%_response.txt
    FileAppend, %response%, debug_batch_%offset%_response.txt, UTF-8
    
    if (response = &quot;ERROR&quot;) {
        return &quot;&quot;
    }
    
    return ParsePostsResponse(response)
}

; Парсинг ответа от execute.getMaxPosts
ParsePostsResponse(response) {
    try {
        json := JSON.Load(response)
        
        ; Проверяем на ошибки API
        if (json.error) {
            error_msg := &quot;Ошибка API: код &quot; json.error.error_code &quot; - &quot; json.error.error_msg
            MsgBox, % error_msg
            return &quot;&quot;
        }
        
        ; Проверяем наличие response
        if (!json.response) {
            MsgBox, Нет response в ответе
            return &quot;&quot;
        }
        
        result := Object()
        result.items := json.response.items ? json.response.items : []
        result.profiles := json.response.profiles ? json.response.profiles : []
        result.groups := json.response.groups ? json.response.groups : []
        result.count := json.response.count ? json.response.count : 0  ; Это поле теперь используется
        
        return result
        
    } catch e {
        MsgBox, Ошибка парсинга JSON батча: %e%
        return &quot;&quot;
    }
}

; Конвертация элемента поста в наш формат
ParsePostItem(post_item, posts_data) {
    post := Object()
    post.photos := []
    post.links := []
    post.videos := []
    post.audios := []
    post.documents := []
    post.polls := []
    post.reposts := []
    post.albums := []
    
    ; Основные поля поста
    post.id := post_item.id
    post.owner_id := post_item.owner_id
    post.from_id := post_item.from_id
    post.date := post_item.date
    post.text := post_item.text ? post_item.text : &quot;&quot;
    post.title := post_item.title ? post_item.title : &quot;&quot;
    
    ; Статистика
    post.likes := post_item.likes.count
    post.reposts := post_item.reposts.count
    post.comments := post_item.comments.count
    post.views := post_item.views.count
    
    ; Извлекаем все виды вложений
    if (post_item.attachments &amp;&amp; post_item.attachments.Length() &gt; 0) {
        for index, attachment in post_item.attachments {
            if (attachment.type = &quot;photo&quot; &amp;&amp; attachment.photo) {
                photo_url := GetLargestPhotoUrl(attachment.photo)
                if (photo_url) {
                    post.photos.Push(photo_url)
                }
            }
            else if (attachment.type = &quot;link&quot; &amp;&amp; attachment.link) {
                link_data := ExtractLinkData(attachment.link)
                if (link_data) {
                    post.links.Push(link_data)
                }
            }
            else if (attachment.type = &quot;video&quot; &amp;&amp; attachment.video) {
                video_data := ExtractVideoData(attachment.video)
                if (video_data) {
                    post.videos.Push(video_data)
                }
            }
            else if (attachment.type = &quot;audio&quot; &amp;&amp; attachment.audio) {
                audio_data := ExtractAudioData(attachment.audio)
                if (audio_data) {
                    post.audios.Push(audio_data)
                }
            }
            else if (attachment.type = &quot;doc&quot; &amp;&amp; attachment.doc) {
                doc_data := ExtractDocumentData(attachment.doc)
                if (doc_data) {
                    post.documents.Push(doc_data)
                }
            }
            else if (attachment.type = &quot;poll&quot; &amp;&amp; attachment.poll) {
                poll_data := ExtractPollData(attachment.poll)
                if (poll_data) {
                    post.polls.Push(poll_data)
                }
            }
            else if (attachment.type = &quot;post&quot; &amp;&amp; attachment.wall) {
                repost_data := ExtractRepostData(attachment.wall)
                if (repost_data) {
                    post.reposts.Push(repost_data)
                }
            }
            else if (attachment.type = &quot;album&quot; &amp;&amp; attachment.album) {
                album_data := ExtractAlbumData(attachment.album)
                if (album_data) {
                    post.albums.Push(album_data)
                }
            }
        }
    }
    
    ; Название группы и screen_name
    post.group_name := &quot;Группа&quot;
    post.group_screen_name := &quot;&quot;
    post.group_avatar := &quot;&quot;
    if (posts_data.groups &amp;&amp; posts_data.groups.Length() &gt; 0) {
        post.group_name := posts_data.groups[1].name
        post.group_screen_name := posts_data.groups[1].screen_name ? posts_data.groups[1].screen_name : &quot;&quot;
        ; Извлекаем аватар группы (лучшее качество)
        if (posts_data.groups[1].photo_200) {
            post.group_avatar := posts_data.groups[1].photo_200
        } else if (posts_data.groups[1].photo_100) {
            post.group_avatar := posts_data.groups[1].photo_100
        } else if (posts_data.groups[1].photo_50) {
            post.group_avatar := posts_data.groups[1].photo_50
        }
    }
    
    ; Если это пост от пользователя, ищем его аватар
    post.user_avatar := &quot;&quot;
    if (post.from_id &gt; 0 &amp;&amp; posts_data.profiles &amp;&amp; posts_data.profiles.Length() &gt; 0) {
        for index, profile in posts_data.profiles {
            if (profile.id = post.from_id) {
                ; Аватар пользователя (лучшее качество)
                if (profile.photo_200) {
                    post.user_avatar := profile.photo_200
                } else if (profile.photo_100) {
                    post.user_avatar := profile.photo_100
                } else if (profile.photo_50) {
                    post.user_avatar := profile.photo_50
                }
                break
            }
        }
    }
    
    return post
}

; Извлечение данных ссылки
ExtractLinkData(link) {
    link_data := Object()
    link_data.url := link.url
    link_data.title := link.title ? link.title : &quot;&quot;
    link_data.description := link.description ? link.description : &quot;&quot;
    link_data.caption := link.caption ? link.caption : &quot;&quot;
    
    ; Извлекаем превью ссылки
    if (link.photo) {
        link_data.preview_url := GetLargestPhotoUrl(link.photo)
    } else {
        link_data.preview_url := &quot;&quot;
    }
    
    return link_data
}

; Извлечение данных видео
ExtractVideoData(video) {
    video_data := Object()
    video_data.id := video.id
    video_data.owner_id := video.owner_id
    video_data.title := video.title ? video.title : &quot;&quot;
    video_data.description := video.description ? video.description : &quot;&quot;
    video_data.duration := video.duration ? video.duration : 0
    
    ; Превью видео
    if (video.image &amp;&amp; video.image.Length() &gt; 0) {
        video_data.preview_url := GetLargestPhotoUrl({&quot;sizes&quot;: video.image})
    } else if (video.first_frame &amp;&amp; video.first_frame.Length() &gt; 0) {
        video_data.preview_url := GetLargestPhotoUrl({&quot;sizes&quot;: video.first_frame})
    } else {
        video_data.preview_url := &quot;&quot;
    }
    
    return video_data
}

; Извлечение данных аудио
ExtractAudioData(audio) {
    audio_data := Object()
    audio_data.artist := audio.artist ? audio.artist : &quot;&quot;
    audio_data.title := audio.title ? audio.title : &quot;&quot;
    audio_data.duration := audio.duration ? audio.duration : 0
    audio_data.url := audio.url ? audio.url : &quot;&quot;
    
    return audio_data
}

; Извлечение данных документа
ExtractDocumentData(doc) {
    doc_data := Object()
    doc_data.id := doc.id
    doc_data.owner_id := doc.owner_id
    doc_data.title := doc.title ? doc.title : &quot;&quot;
    doc_data.ext := doc.ext ? doc.ext : &quot;&quot;
    doc_data.url := doc.url ? doc.url : &quot;&quot;
    doc_data.size := doc.size ? doc.size : 0
    doc_data.date := doc.date ? doc.date : 0
    doc_data.access_key := doc.access_key ? doc.access_key : &quot;&quot;
    
    ; Превью документа (если есть)
    if (doc.preview &amp;&amp; doc.preview.photo &amp;&amp; doc.preview.photo.sizes) {
        doc_data.preview_url := GetLargestPhotoUrl(doc.preview.photo)
    } else {
        doc_data.preview_url := &quot;&quot;
    }
    
    return doc_data
}

; Извлечение данных опроса
ExtractPollData(poll) {
    poll_data := Object()
    poll_data.id := poll.id
    poll_data.owner_id := poll.owner_id
    poll_data.question := poll.question ? poll.question : &quot;&quot;
    poll_data.votes := poll.votes ? poll.votes : 0
    poll_data.answers := []
    
    ; НОВЫЕ ПОЛЯ ДЛЯ ОПРОСА
    poll_data.anonymous := poll.anonymous ? poll.anonymous : 0
    poll_data.multiple := poll.multiple ? poll.multiple : 0
    poll_data.end_date := poll.end_date ? poll.end_date : 0
    poll_data.closed := poll.closed ? poll.closed : 0
    poll_data.is_board := poll.is_board ? poll.is_board : 0
    poll_data.can_edit := poll.can_edit ? poll.can_edit : 0
    poll_data.can_vote := poll.can_vote ? poll.can_vote : 0
    poll_data.can_report := poll.can_report ? poll.can_report : 0
    poll_data.can_share := poll.can_share ? poll.can_share : 0
    poll_data.author_id := poll.author_id ? poll.author_id : 0
    poll_data.background := poll.background ? poll.background : &quot;&quot;
    
    if (poll.answers &amp;&amp; poll.answers.Length() &gt; 0) {
        for index, answer in poll.answers {
            answer_data := Object()
            answer_data.id := answer.id
            answer_data.text := answer.text ? answer.text : &quot;&quot;
            answer_data.votes := answer.votes ? answer.votes : 0
            answer_data.rate := answer.rate ? answer.rate : 0
            poll_data.answers.Push(answer_data)
        }
    }
    
    return poll_data
}

; Извлечение данных репоста
ExtractRepostData(wall) {
    repost_data := Object()
    repost_data.id := wall.id
    repost_data.owner_id := wall.owner_id
    repost_data.from_id := wall.from_id
    repost_data.date := wall.date
    repost_data.text := wall.text ? wall.text : &quot;&quot;
    
    ; Статистика репоста
    if (wall.likes) {
        repost_data.likes := wall.likes.count
    }
    if (wall.reposts) {
        repost_data.reposts := wall.reposts.count
    }
    if (wall.comments) {
        repost_data.comments := wall.comments.count
    }
    if (wall.views) {
        repost_data.views := wall.views.count
    }
    
    return repost_data
}

; Извлечение данных альбома
ExtractAlbumData(album) {
    album_data := Object()
    album_data.id := album.id
    album_data.owner_id := album.owner_id
    album_data.title := album.title ? album.title : &quot;&quot;
    album_data.description := album.description ? album.description : &quot;&quot;
    album_data.size := album.size ? album.size : 0
    
    ; Обложка альбома
    if (album.thumb &amp;&amp; album.thumb.sizes) {
        album_data.thumb_url := GetLargestPhotoUrl(album.thumb)
    } else {
        album_data.thumb_url := &quot;&quot;
    }
    
    return album_data
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (1srafel)]]></author>
			<pubDate>Wed, 22 Oct 2025 20:28:10 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=162776#p162776</guid>
		</item>
	</channel>
</rss>
