Can you help me why this fails for some threads?

line 111, in sendList
    tempMessage=arr[a]['message']
                ~~~^^^
KeyError: 0

# grab_server.py

import os,requests,math,json,copy,html,time,re,traceback,sys
from datetime import datetime
from PIL import Image
from flask import session

import settings,imagesize


def sendList(obj,obj2,obj3,bid,catalog=False):

    pageFormat=generatePageFormat(session)

    threadsTotal=obj

    pageLinks=""

    if catalog==False:
        for a in range(1,math.ceil(threadsTotal/10)+1):
            no=str(a)
            if (a!=obj3):
                if (a<50):
                    pageLinks+=f"<a href='/{bid}/p/{no}'>"+no+"</a> "
                else:
                    if (a%20==0):
                        pageLinks+=f"<a href='/{bid}/p/{no}'>"+no+"</a> "
                    if (a==math.ceil(threadsTotal/10) and a!={obj3}):
                        pageLinks+=f"<a href='/{bid}/p/{no}'>{no}</a>"
            elif (a==obj3):
                pageLinks+=no+" "

    elif catalog==True:
        for a in range(1,math.ceil(threadsTotal/150)+1):
            no=str(a)
            if (a!=obj3):
                if (a<50):
                    pageLinks+=f"<a href='/{bid}/catalog/p/{no}'>"+no+"</a> "
                else:
                    if (a%20==0):
                        pageLinks+=f"<a href='/{bid}/catalog/p/{no}'>"+no+"</a> "
                    if (a==math.ceil(threadsTotal/150) and a!={obj3}):
                        pageLinks+=f"<a href='/{bid}/catalog/p/{no}'>{no}</a>"
            elif (a==obj3):
                pageLinks+=no+" "

    
    arr=obj2

    arrPrep={}
    postPrep=""
    appendixMessage={}
    
    if 'wide' in session:
        if session['wide']==True:
            wideFormat='max-width:780px;'
        elif session['wide']==False:
            wideFormat=''
    else:
        wideFormat='max-width:780px;'

    if 'watch' in session:
        if session['watch']==True:
            watchFormat='<details class="modal" open="">'
        elif session['watch']==False:
            watchFormat='<details class="modal">'
    else:
        watchFormat='<details class="modal" open="">'

    arrPrep=f'''<div id="sticky"><table style="width:100%;margin-top:-5px;{wideFormat}font-size:10pt;"><tbody><tr><td style="text-align: left;width:27%;"><a href="/{bid}">↑ Home</a>&nbsp;&nbsp;<a href="/{bid}/catalog">Catalog</a> {watchFormat}
            <summary class="modal__toggle2"></summary>

                <div class="modal__body2" tabindex="-1" role="dialog" aria-labelledby="modal__label" aria-live="assertive" aria-modal="true">

<iframe src="http://127.0.0.1:8000/watch"  width="100%" style="height:100%; border:none;"></iframe>


                </div>

        </details>'''+generateSettings()+f'''       </td><td style="text-align:center;">'''
        
    if catalog==True:
        arrPrep+=f'''<a href="/{bid}/catalog/p/{str(obj3-1) if ((obj3)>1) else str(obj3)}">←</a> page {str(obj3)} <a href="/{bid}/catalog/p/{str(obj3+1) if obj3!=math.ceil(threadsTotal/150) else str(obj3)}">→</a>'''
    elif catalog==False:
        arrPrep+=f'''<a href="/{bid}/p/{str(obj3-1) if ((obj3)>1) else str(obj3)}">←</a> page {str(obj3)} <a href="/{bid}/p/{str(obj3+1) if obj3!=math.ceil(threadsTotal/10) else str(obj3)}">→</a>'''
            
    arrPrep+=f'</td><td style="text-align: right;width:35%;"><div class="boardList" style="max-width: 30%;"><span style="width:50px;display:block;">↷ /{settings.temp_prefs[settings.temp_prefs.index(bid)]}/</span><div class="boardList-content">'
    
    for v in settings.temp_prefs:
        if v!=bid:
            if catalog==False:
                arrPrep+=f'<p><a href="/{v}">/{v}/</a></p>'
            if catalog==True:
                arrPrep+=f'<p><a href="/{v}/catalog">/{v}/</a></p>'
            
    arrPrep+=f'</div></div> <form action="/search" method="get" style="display:inline;"><input style="width:61%;min-width:87.95px;font-size:10pt;max-width: 50%" type="text" placeholder="Search all boards" id="q" name="q"> <input style="font-size:10pt;" type="submit" value="Find"></form></td></tr></tbody></table><hr><div id="empty" style="padding-top:4px"></div></div>'

    
    #arrPrep+='<div style="text-align:right">page '+str(obj3)+'</div><br style="line-height: 0.3;">'

    j=0
    jApp='<hr>'
    imgList=""
    catPrep=""

    for a in range(0,len(arr)):

        appendixMessage[a]=''


        i=0
        
        tempMessage=arr[a]['message']

        if len(arr[a]['message'])>50:
            if len(arr[a]['message'])>1000:
                tempMessage=arr[a]['message'][:1000]
                appendixMessage[a]=f'...</pre><pre style="display:inline;"><a href="/{bid}/t/{str(arr[a]["threadId"])}"><b>[expand thread]</b></a>'

        if str(arr[a]['subject'])=='None':
            arr[a]['subject']=''      
        else:
            arr[a]['subject']=arr[a]['subject']+' '

        sizeImages=0
        countImages=1

        sizeImages+=len(arr[a]['files'])

        if catalog==False:
            imgList,countImages,currentIteration=gatherThumbs(arr[a],imgList,sizeImages,countImages,0,False)
        elif catalog==True:
            imgList,countImages,currentIteration=gatherThumbs(arr[a],imgList,sizeImages,countImages,0,False,True)

        threadId=str(arr[a]['threadId'])
        
        tempMessage=escapeMessage(tempMessage,threadId,bid)
        
        appendixFlag=''
        autoSage=''
        
        if 'flag' in arr[a]:
            if arr[a]['flag'] is not None:
                appendixFlag='<img src="/media/flags'+arr[a]['flag'][14:]+'"> '

        if 'autoSage' in arr[a]:
            if arr[a]['autoSage'] is not False:
                autoSage='  <span style="color:red;font-weight: bold;">SÄGE!</span>'

        if (imgList!="" or tempMessage!=""):
            postPrep+='<span id="faden"><b id="postTitle">'+appendixFlag+arr[a]['subject']+'</b><b id="authorTitle">'+arr[a]['name']+'</b> '+arr[a]['creation']+' No. <a id="'+str(arr[a]['threadId'])+f'" href="/{bid}/t/'+str(arr[a]['threadId'])+'">'+str(arr[a]['threadId'])+f'</a> <a href="/{bid}/t/{str(arr[a]["threadId"])}/watch">[+]</a>'+autoSage+'<pre>'+imgList+'<div id="textContent">'+tempMessage+appendixMessage[a]+'</div></pre><div id="empty" style="padding-top:4px"></div><pre><div id="posts">'


        catPrep+='''
      <article>
        '''+'<b id="postTitle" style="font-size:13px">'+appendixFlag+arr[a]['subject']+'</b> <b><a id="'+str(arr[a]['threadId'])+f'" href="/{bid}/t/'+str(arr[a]['threadId'])+'">#'+str(arr[a]['threadId'])+f'</a> <a href="/{bid}/t/{str(arr[a]["threadId"])}/watch">[+]</a> </b><pre><a href="/{bid}/t/'+str(arr[a]['threadId'])+'">'+imgList+'</a><div id="textContent">'+tempMessage+appendixMessage[a]+'</div></pre><div id="empty" style="padding-top:4px"></div>''''
      </article>
    '''
    
        imgList=""

        arrSort=''
        
            

        for b in reversed(arr[a]['posts']):
            if i<4:
                if str(b['subject'])=='None':
                    b['subject']=''
                else:
                    b['subject']+=' '

                sizeImages=0
                countImages=1

                sizeImages+=len(b['files'])

                imgList,countImages,currentIteration=gatherThumbs(b,imgList,sizeImages,countImages,0,False)

                threadId=str(arr[a]['threadId'])
                
                b['message']=escapeMessage(b['message'],threadId,bid)
                
                appendixFlag=''
                sage=''
        
                if 'flag' in b:
                    if b['flag'] is not None:
                        appendixFlag='<img src="/media/flags'+b['flag'][14:]+'"> '

                if 'email' in b:
                    if b['email'] is not None:
                        sage='  <span style="color:red;font-weight: bold;">SÄGE!</span>'

                if len(b['message'])>50:
                    if len(b['message'])>1000:
                        b['message']=b['message'][:1000]
                        b['message']+=f'...</pre><pre style="display:inline;"><a href="/{bid}/t/{str(arr[a]["threadId"])}#{str(b["postId"])}"><b>[expand post]</b></a>'    
                if (imgList!="" or b['message']!=""): 
                    arrSort=f'<span id="post"><div id="{str(b['postId'])}" class="post"><b id="postTitle">'+appendixFlag+b['subject']+'</b><b id="authorTitle">'+b['name']+'</b> '+b['creation']+' No. <a id="'+str(arr[a]['threadId'])+f'" href="/{bid}/t/'+str(arr[a]['threadId'])+'#'+str(b['postId'])+'">'+str(b['postId'])+'</a>'+sage+'<pre>'+imgList+'<div id="textContent">'+(b['message'])+'</div></pre></div></span>'+arrSort
                    i+=1

                imgList=""

        postPrep+=arrSort
        
        if (len(arr[a]['posts'])-(i)>0):
            j+=1
            if (j==len(arr)):
                jApp=str('')
            postPrep+=f'</pre></div><div id="notshown"><div id="posts">'+str(len(arr[a]['posts'])-(i))+f' post(s) not shown. <a href="/{bid}/t/{(arr[a]["threadId"])}">Show all</a><br></div></div><br>{jApp}<div id="empty" style="padding-top:4px"></div>'
        else:
            j+=1
            if (j==len(arr)):
                jApp=str('')
            postPrep+=f'</pre></div><div id="posts">&lhblk;<br></div><br>{jApp}<div id="empty" style="padding-top:4px"></div>'



    if catalog==True:
            return '<!DOCTYPE html><head><title>KC-Archive</title><meta name = "viewport" content = "width = device-width">'+pageFormat+arrPrep+'<span id="faden"><section>'+catPrep+'</section><br><br><div style="text-align:right;">'+str(threadsTotal)+' threads ('+str(math.ceil(threadsTotal/150))+' pages)</div><hr><div style="text-align:justify; white-space:initial;font-size:10pt;">'+pageLinks+'</div>'


    return '<!DOCTYPE html><head><title>KC-Archive</title><meta name = "viewport" content = "width = device-width">'+pageFormat+arrPrep+postPrep+'<br><br><div style="text-align:right;">'+str(threadsTotal)+' threads ('+str(math.ceil(threadsTotal/10))+' pages)</div><hr><div style="text-align:justify; white-space:initial;font-size:10pt;">'+pageLinks+'</div>'
    
    #'<h2 style="margin-top:2pt;">'+arr['message'][:50]+appendixTitle+'</h2>


def showThread(obj,obj2,obj3,bid,avail):

    pageFormat=generatePageFormat(session)

    dt=datetime.now()

    threadsTotal=obj

    pageLinks=""


    for a in range(1,math.ceil(threadsTotal/10)+1):
        no=str(a)
        if (a<50):
            pageLinks+=f"<a href='/{bid}/p/{no}'>"+no+"</a> "
        else:
            if (a%20==0):
                pageLinks+=f"<a href='/{bid}/p/{no}'>"+no+"</a> "
            if (a==math.ceil(threadsTotal/10) and a!={obj3}):
                pageLinks+=f"<a href='/{bid}/p/{no}'>{no}</a>"


    
    arr=obj2

    arrPrep={}
    appendixMessage={}

    if 'wide' in session:
        if session['wide']==True:
            wideFormat='max-width:780px;'
        elif session['wide']==False:
            wideFormat=''
    else:
        wideFormat='max-width:780px;'

    if 'watch' in session:
        if session['watch']==True:
            watchFormat='<details class="modal" open="">'
        elif session['watch']==False:
            watchFormat='<details class="modal">'
    else:
        watchFormat='<details class="modal" open="">'

    arrPrep=f'''<table style="width:100%;margin-top:-5px;{wideFormat}font-size:10pt;"><tbody><tr><td style="text-align: left;width:27%;"><a href="/{bid}">← Back</a>&nbsp;&nbsp;<a href="/{bid}/catalog">Catalog</a> {watchFormat}
            <summary class="modal__toggle2"></summary>

                <div class="modal__body2" tabindex="-1" role="dialog" aria-labelledby="modal__label" aria-live="assertive" aria-modal="true">

<iframe src="http://127.0.0.1:8000/watch"  width="100%" style="height:100%; border:none;"></iframe>


                </div>

        </details>'''+generateSettings()+f'''</td><td style="text-align: center;"><i><small>saved: {dt}</small></i></td><td style="text-align: right;width:35%;"><div class="boardList" style="max-width: 30%;">'''
    
    arrPrep+=f'<span style="width:50px;display:block;">↷ /{settings.temp_prefs[settings.temp_prefs.index(bid)]}/</span><div class="boardList-content">'
    
    for v in settings.temp_prefs:
        if v!=bid:
            arrPrep+=f'<p><a href="/{v}">/{v}/</a></p>'
    
    arrPrep+=f'</div></div> <form action="/search" method="get" style="display:inline;"><input style="width:61%;min-width:87.95px;font-size:10pt;max-width: 50%" type="text" placeholder="Search all boards" id="q" name="q"> <input style="font-size:10pt;" type="submit" value="Find"></form></td></tr></tbody></table><hr><div id="empty" style="padding-top:4px"></div>'
    imgList=""

    for a in range(0,len(arr)):

        appendixMessage[a]=''


        if str(arr[a]['subject'])=='None':
            arr[a]['subject']=''      
        else:
            arr[a]['subject']=arr[a]['subject']+' '

        sizeImages=0
        countImages=1

        sizeImages+=len(arr[a]['files'])

        imgList,countImages,currentIteration=gatherThumbs(arr[a],imgList,sizeImages,countImages,0,False)

        threadId=str(arr[a]['threadId'])

        arr[a]['message']=escapeMessage(arr[a]['message'],threadId,bid)
        
        appendixFlag=''
        autoSage=''
        
        if 'flag' in arr[a]:
            if arr[a]['flag'] is not None:
                appendixFlag='<img src="/media/flags'+arr[a]['flag'][14:]+'"> '

        if 'autoSage' in arr[a]:
            if arr[a]['autoSage'] is not False:
                autoSage='  <span style="color:red;font-weight: bold;">SÄGE!</span>'                    

        if (imgList!="" or arr[a]['message']!=""):

            url=f" <a href='{settings.board}/{bid}/res/{str(arr[a]["threadId"])}.html'>🟢</a>"
            arrPrep+='<span id="faden"><b id="postTitle">'+appendixFlag+arr[a]['subject']+'</b><b id="authorTitle">'+arr[a]['name']+'</b> '+arr[a]['creation']+' No. <a id="'+str(arr[a]['threadId'])+f'" href="/{bid}/t/'+str(arr[a]['threadId'])+'">'+str(arr[a]['threadId'])+f'</a> {url if avail==True else " 🔴"} <a href="/{bid}/t/{str(arr[a]["threadId"])}/watch">[+]</a>'+autoSage+'<pre>'+imgList+'<div id="textContent">'+arr[a]['message']+'</div></pre><div id="empty" style="padding-top:4px"></div><pre><div id="posts">'

        imgList=""

        arrSort=''

        for b in reversed(arr[a]['posts']):

            if str(b['subject'])=='None':
                b['subject']=''
            else:
                b['subject']+=' '

            sizeImages=0
            countImages=1

            sizeImages+=len(b['files'])

            imgList,countImages,currentIteration=gatherThumbs(b,imgList,sizeImages,countImages,0,False)


            threadId=str(arr[a]['threadId'])

            b['message']=escapeMessage(b['message'],threadId,bid)
            
            appendixFlag=''
            sage=''
            
            if 'flag' in b:
                if b['flag'] is not None:
                    appendixFlag='<img src="/media/flags'+b['flag'][14:]+'"> ' 

            if 'email' in b:
                if b['email'] is not None:
                    sage='  <span style="color:red;font-weight: bold;">SÄGE!</span>'           

            if (imgList!="" or b['message']!=""):
                arrSort=f'<div id="{str(b['postId'])}" class="post"><b id="postTitle">'+appendixFlag+b['subject']+'</b><b id="authorTitle">'+b['name']+'</b> '+b['creation']+' No. <a id="'+str(b['postId'])+f'" href="/{bid}/t/'+str(arr[a]['threadId'])+'#'+str(b['postId'])+'">'+str(b['postId'])+'</a>'+sage+'<pre>'+imgList+'<div id="textContent">'+(b['message'])+'</div></pre></div>'+arrSort

            imgList=""


        arrPrep+=arrSort
        arrPrep+='</pre></div><div id="posts">&lhblk;<br><br><br></div>'


    return '<!DOCTYPE html><head><title>'+str(re.sub('<[^<]+?>', '', arr[0]['message'][:500]))+' | KC-Archive</title><meta name = "viewport" content = "width = device-width">'+pageFormat+arrPrep+'<br><br><a id="end"></a><div style="text-align:right;">'+str(threadsTotal)+' threads ('+str(math.ceil(threadsTotal/10))+' pages)</div><hr><div style="text-align:justify; white-space:initial;font-size:10pt;">'+pageLinks+'</div>'


def gatherThumbs(obj,imgList,sizeImg,countImg,currIter,load=True,lazy=False):

    try:
        if ('posts' in obj.keys()):

            for c in obj['posts']:
                if 'flag' in c:
                    try:
                        flagpath=""
                        flagpath=f"./media/flags/{c['flag'][14:]}"
                        if os.path.exists(flagpath)==False:
                            myfile2 = requests.get(f"{settings.board}{c['flag']}",proxies=settings.proxies,headers=settings.headers)
                            # Assuming flagpath is the full path including the filename
                            directory = os.path.dirname(flagpath)

                            # Create the directory if it doesn't exist
                            os.makedirs(directory, exist_ok=True)
                            open(flagpath, 'wb').write(myfile2.content)

                            sys.stdout.write('\n'+flagpath+' saved ('+str(round(time.time()))+')')
                            sys.stdout.flush()

                            currIter+=1
                    except Exception as e:
                        print('FlagError '+e)
                    
        if ('files' in obj.keys()):

            for c in obj['files']:
                if (c['mime']!='aaaaaaaaaaaaa'):
                    #print('\r'+c['thumb'])
                    
                    
                    try:
                        localpath=f"./media/{c['thumb'][7:]}.webp"
                        localpath2=f"./media/{c['thumb'][7:]}.png"


                        if os.path.exists(localpath)==False and load is True and currIter<5:
                            myfile = requests.get(f"{settings.board}{c['thumb']}",proxies=settings.proxies,headers=settings.headers)
                            
                            if settings.compress_pref==True:
                               open(localpath, 'wb').write(myfile.content)
                               image = Image.open(localpath)  # Open image
                               
                               image.save(localpath, format="webp")  # Convert image to webp
                               sys.stdout.write('\n['+str(countImg)+'/'+str(sizeImg)+'] '+localpath+' saved ('+str(round(time.time()))+')')
                               sys.stdout.flush()
                            
                            elif settings.compress_pref==False:
                               open(localpath2, 'wb').write(myfile.content)
                               image = Image.open(localpath2)  # Open image
                               
                               image.save(localpath2, format="png")  # Save image to png
                               
                               sys.stdout.write('\n'+localpath2+' saved ('+str(round(time.time()))+')')
                               sys.stdout.flush()

                            currIter+=1

                        
                        #gatherFlags(obj,True)

                        if os.path.exists(localpath)==True:
                          width,height=imagesize.get(localpath)
                          if lazy==False:
                           imgList+=f"<img src='/media/{c['thumb'][7:]}.webp' style='max-width:165px;float:left;margin-right:10px;margin-bottom:10px;' width='{width}' height='{height*(165/width) if width>165 else height}'>"
                          elif lazy==True:
                           imgList+=f"<img src='/media/{c['thumb'][7:]}.webp' style='max-width:165px;float:left;margin-right:10px;margin-bottom:10px;'  width='{width}' height='{height*(165/width) if width>165 else height}' loading='lazy'>"
                        elif os.path.exists(localpath2)==True:
                          if lazy==False:
                           imgList+=f"<img src='/media/{c['thumb'][7:]}.png' style='max-width:165px;float:left;margin-right:10px;margin-bottom:10px;'>"
                          elif lazy==True:
                           imgList+=f"<img src='/media/{c['thumb'][7:]}.png' style='max-width:165px;float:left;margin-right:10px;margin-bottom:10px;' loading='lazy'>"



                    except:
                        pass

                    countImg+=1
    except:
        imgList=""
    

    return imgList,countImg,currIter


def generatePageFormat(session):

    if 'wide' in session:
        if session['wide']==True:
            wideFormat='max-width:780px;'
        elif session['wide']==False:
            wideFormat=''
    else:
        wideFormat='max-width:780px;'
    
    pageFormat='''<style>body { font-family: Verdana,Tahoma,Arial,sans-serif; font-size: 10pt;'''+wideFormat+''' margin: 0 auto; padding-left: 10px; padding-right: 10px; padding-top: 12px; padding-bottom:12px; background: #eeeeee; overflow-x: hidden; } pre {  white-space: pre-wrap; font-family:Verdana,Tahoma,Arial,sans-serif; font-size:10pt; overflow: hidden; margin-bottom: 2px; line-height:1.4; } hr { border: none; height: 1px; background-color: #333; /* Modern browsers */ } div#posts { margin-left:10%; } a { text-decoration: azure; } #postTitle { color: #c80000; font-size: 12pt; font-weight: bold; } #authorTitle { color: #2f13f9; font-weight:bold; } .post { background-color:bisque;padding:6pt 10pt 10pt;border-style:ridge; margin-bottom: 4pt; border-radius:8px; border-width:2px; border-inline:white; overflow: visible; position: relative; } .boardList { position: relative; display: inline-block; padding-right: 5px; cursor: default; text-align: center; } .boardList-content { display: none; position: absolute; background-color: #eeeeee; z-index: 1; } .boardList:hover .boardList-content { display: block; width: 50px; } a { text-decoration:none; } 
    

.modal {
	display: inline;
}

.modal[open] .modal__toggle {
    left: calc(50vw + 140px);
    top: calc(15vh + 20px);
    position: fixed;
    z-index: 2;
}
.modal[open] .modal__toggle:focus {
    outline: 2px solid #00f;
}
.modal__toggle::before {
    content: '  Settings';
    white-space: pre;
}
.modal[open] .modal__toggle::before {
    content: '✖';
}
.modal__toggle {
    color: #00f;
    list-style: none;
}
.modal__toggle::-webkit-details-marker {
    display: none;
}
.modal__toggle:hover {
    cursor: pointer;
    opacity: .8;
}
/*
.modal[open] .modal__toggle2 {
    left: calc(30vw + 15px);
    top: calc(15vh + 20px);
    position: fixed;
    z-index: 2;
}*/
.modal[open] .modal__toggle2:focus {
    outline: 2px solid #00f;
}
.modal__toggle2::before {
    content: ' ↙️';
    white-space: pre;
}

.modal__toggle2 {
    color: #00f;
    list-style: none;
}
.modal__toggle2::-webkit-details-marker {
    display: none;
}
.modal__toggle2:hover {
    cursor: pointer;
    opacity: .8;
}
.modal__background {
    background-color:rgba(0, 0, 0, .25);
    display: flex;
    height: 100vh;
    justify-content: center;
    left: 0;
    opacity: .9;
    position: fixed;
    top: 0;
    width: 100vw;
    z-index: 1;
}
.modal__body {
    background-color: #fff;
    box-shadow: 0 0 10px rgba(0, 0, 0, .25);
    font-weight: 700;
    padding: 20px 40px;
    position: fixed;
    top: 15vh;
    width: 300px;
    z-index: 1;
}
.modal__body2 {
    background-color: #fff;
    box-shadow: 0 0 10px rgba(0, 0, 0, .25);
    font-weight: 700;
    position: fixed;
    top: 15vh;
    left: 0;
    width: 24%;
    height: 60%;
    opacity: 85%;
    z-index: 1;
    max-width: 320px;
}

section {
   display: flex;
   flex-wrap: wrap;
}

article {
   flex: 150px;
   height: 250px;
   overflow: hidden;
   margin: 5px;
}

article:hover {
   background: #aac;
}

.spoiler{
  background-color: black;
  color: transparent;

  span {
    color: transparent !important;
  }

  a {
  color: transparent;
  }

  a:hover {
  color: white;
  }
}

.spoiler:hover{
  color: white !important;

  span {
    color: white !important;
  }
}

#faden:hover {
  position: relative;
  margin: 0px -20px 0px -25px;
  padding: 0px 20px 0px 25px;
  box-shadow: 0 0 15px 10px #eeeeee;
  background-color: #eeeeee;
  z-index: 2;
  display: block;
} 

.greentext {
  display:inline-block;
  color:green;
}

.redtext {
  display:inline-block;
  color:red;
}

.post:target {
    outline: 2px dashed #00f;
    outline-offset: -2px;
}

img {
    transition: transform 0.3s ease-in-out;
}

img:hover {
    transform: scale(1.4);
    z-index: 9999;
    position: relative;
}

.post:hover pre {
    display: flow-root;
    overflow: visible !important;
    background-color: none;
}

span#faden:hover pre {
    display: flow-root;
    overflow: visible !important;
    background-color: none;
}

#textContent {
    overflow: clip;
}

span#faden,
span#post,
#notshown,
#notshown i,
#notshown b,
#notshown u,
#notshown em,
#notshown strong {
    font-weight: normal;
    font-style: normal;
    text-decoration: none;
}


    </style></head>'''

    return pageFormat


def generateSettings():
    import settings

    if 'wide' in session:
        if session['wide']==True:
            wideSet='checked'
        else:
            wideSet=''
    else:
        session['wide']=True
        wideSet='checked'

    if 'watch' in session:
        if session['watch']==True:
            watchSet='checked'
        else:
            watchSet=''
    else:
        session['watch']=True
        watchSet='checked'
    	
    if settings.compress_pref==True:
        compressSet='checked'
    elif settings.compress_pref==False:
        compressSet=''
	
    settings='''<details class="modal">
            <summary class="modal__toggle"></summary>
            <div class="modal__background">
                <div class="modal__body" tabindex="-1" role="dialog" aria-labelledby="modal__label" aria-live="assertive" aria-modal="true">
                    <p id="modal__label"><form action="/settings" method="post" id="set1"><fieldset>
    <legend>Settings:</legend>

    <div>
      <input type="checkbox" id="fwidth" name="fwidth" '''+wideSet+'''>
      <label for="fwidth">Fixed width</label>
    </div>

    <div>
      <input type="checkbox" id="fwatch" name="fwatch" '''+watchSet+'''>
      <label for="fwatch">Show thread watcher</label>
    </div>
    
    <div>
      <input type="checkbox" id="fcompress" name="fcompress" '''+compressSet+'''>
      <label for="fcompress">Compress images to .webp</label>
    </div>
    
    <div>
      <input type="checkbox" id="fres" name="fres">
      <label for="fres">Save images in original resolution (takes up a lot of space)</label>
    </div>
</fieldset>
<br><input type="submit"  value="Apply" style="font-weight:700;" id="set1" /></form>
</p>
                </div>
            </div>
        </details>'''
    return settings
    

def gatherFlags(obj,load):

    if ('posts' in obj.keys()):
        for c in obj['posts']:
            if 'flag' in c:
                flagpath=""
                flagpath=f"./media/flags/{c['flag'][14:]}"
                if os.path.exists(flagpath)==False and load is True:
                    myfile2 = requests.get(f"{settings.board}{c['flag']}",proxies=settings.proxies,headers=settings.headers)
                    # Assuming flagpath is the full path including the filename
                    directory = os.path.dirname(flagpath)

                    # Create the directory if it doesn't exist
                    os.makedirs(directory, exist_ok=True)
                    open(flagpath, 'wb').write(myfile2.content)

                    sys.stdout.write('\n'+flagpath+' saved ('+str(round(time.time()))+')')
                    sys.stdout.flush()


def escapeMessage(arr,id,bid):


    
    arr=html.escape(arr)
    arr=re.sub(r'((https?):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)', r'<a href="\1" target="_blank">\1</a>', arr)
    arr=re.sub(r'\&lt;tinyboard(.*?)\&gt;(.*?)\&lt;/tinyboard\&gt;', r'', arr)
    arr=re.sub(r'&gt;&gt;&gt;.*?(\d*|$)', rf'<a href="/{bid}/t/{id}#\1">>>\1</a>', arr)
    arr=re.sub(r'&gt;&gt;.*?(\d*|$)', rf'<a href="/{bid}/t/{id}#\1">>>\1</a>', arr)
    arr=re.sub(r'\*\*(.*?(\d*|$))\*\*', rf'<span class="spoiler">\1</span>', arr)

    arr=re.sub("&gt;.*?(.*|$)", rf'<span class="greentext">&gt;\1</span>', arr)
    arr=re.sub("&lt;.*?(.*|$)", rf'<span class="redtext">&lt;\1</span>', arr)

    arr=re.sub(r'\[b\]([\s\S]*?(\d*|$))\[/b]', rf'<b>\1</b>', arr)
    arr=re.sub(r'\[i\]([\s\S]*?(\d*|$))\[/i]', rf'<i>\1</i>', arr)
    arr=re.sub(r'\[u\]([\s\S]*?(\d*|$))\[/u]', rf'<u>\1</u>', arr)
    arr=re.sub(r'\[s\]([\s\S]*?(\d*|$))\[/s]', rf'
\1
', arr)
    arr=re.sub(r'&#x27;&#x27;&#x27;([\s\S]*?(.*|$))\&#x27;&#x27;&#x27;', rf'<b>\1</b>', arr)

    arr=re.sub(r'\[spoiler\](.*?(\d*|$))\[/spoiler]', rf'<span class="spoiler">\1</span>', arr, flags=re.DOTALL)
    arr=re.sub(r'==(.*?(\d*|$))==', rf'<span style="color:#af0a0f;font-size:12pt;font-weight:bold;">\1</span>', arr, flags=re.DOTALL)
    
    return arr