<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Denil's Blog]]></title><description><![CDATA[Denil's Blog]]></description><link>https://denil.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 25 Sep 2026 20:51:34 GMT</lastBuildDate><atom:link href="https://denil.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Automating SIH Team Registrations: Making Life Easier for College SPOCs]]></title><description><![CDATA[Automating SIH Team Registrations: Making Life Easier for College SPOCs
Hello, fellow developers and automation enthusiasts! If you've ever faced the daunting task of manually entering details for multiple teams into a portal, you'll love what's comi...]]></description><link>https://denil.hashnode.dev/automating-sih-team-registrations-making-life-easier-for-college-spocs</link><guid isPermaLink="true">https://denil.hashnode.dev/automating-sih-team-registrations-making-life-easier-for-college-spocs</guid><category><![CDATA[SIH 2023]]></category><category><![CDATA[automation]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Denil Bhatt]]></dc:creator><pubDate>Thu, 12 Oct 2023 05:25:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697005541154/7f71a7df-67dd-494f-a89c-2ad9dd706e88.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-automating-sih-team-registrations-making-life-easier-for-college-spocs">Automating SIH Team Registrations: Making Life Easier for College SPOCs</h1>
<p>Hello, fellow developers and automation enthusiasts! If you've ever faced the daunting task of manually entering details for multiple teams into a portal, you'll love what's coming next. Today, I'm sharing how we automated the Smart India Hackathon (SIH) registration process for our college, saving countless hours of manual data entry.</p>
<h2 id="heading-the-challenge"><strong>The Challenge</strong>:</h2>
<p>Registering numerous teams on the SIH portal. Each entry required information like team name, problem number, details of each team member, and a consent letter from the college.</p>
<h2 id="heading-the-solution"><strong>The Solution</strong>:</h2>
<p>After close inspection of the portal's registration flow, it was apparent that the entire process culminated in a singular POST request to their backend. This was our eureka moment! We realized we could automate the process by simulating this POST request.</p>
<p>Before we take a look at the script, let me show you the format I followed for the input csv file containing team details:</p>
<pre><code class="lang-csv">final_id,team_id,team_name,ps_number,category,status,Mentor Name,Mentor 2 Name,member_1,member_1_enrollment,member_1_gender,member_1_email,member_1_mobile,member_2,member_2_enrollment,member_2_gender,member_2_email,member_2_mobile,member_3,member_3_enrollment,member_3_gender,member_3_email,member_3_mobile,member_4,member_4_enrollment,member_4_gender,member_4_email,member_4_mobile,member_5,member_5_enrollment,member_5_gender,member_5_email,member_5_mobile,member_6,member_6_enrollment,member_6_gender,member_6_email,member_6_mobile
40,89,Study Stars,SIH1420,Software,shortlist,Dr. Alex Smith,John Doe,Michael Johnson,22ABC001,M,michael.j22@fakecollege.edu,1234567890,Emily Davis,22ABC002,F,emily.d22@fakecollege.edu,1234567891,James Martin,22ABC003,M,james.m22@fakecollege.edu,1234567892,Emma Thompson,22ABC004,F,emma.t22@fakecollege.edu,1234567893,William Jones,22ABC005,M,william.j22@fakecollege.edu,1234567894,Elizabeth Taylor,22ABC006,F,elizabeth.t22@fakecollege.edu,1234567895
41,72,Code Warriors,SIH1440,Software,shortlist,Dr. Brian Lee,0,Olivia Wilson,22ABC007,F,olivia.w22@fakecollege.edu,1234567896,David Brown,22ABC008,M,david.b22@fakecollege.edu,1234567897,Sophia Clark,22ABC009,F,sophia.c22@fakecollege.edu,1234567898,Liam Hall,22ABC010,M,liam.h22@fakecollege.edu,1234567899,Mia Turner,22ABC011,F,mia.t22@fakecollege.edu,12345678910,Noah White,22ABC012,M,noah.w22@fakecollege.edu,12345678911
42,53,DigiMinds,SIH1450,Software,shortlist,Dr. Charles Moore,0,Ava Taylor,22ABC013,F,ava.t22@fakecollege.edu,12345678912,Joseph Lewis,22ABC014,M,joseph.l22@fakecollege.edu,12345678913,Isabella Harris,22ABC015,F,isabella.h22@fakecollege.edu,12345678914,Ethan Robinson,22ABC016,M,ethan.r22@fakecollege.edu,12345678915,Isabelle Walker,22ABC017,F,isabelle.w22@fakecollege.edu,12345678916,Benjamin Wright,22ABC018,M,benjamin.w22@fakecollege.edu,12345678917
</code></pre>
<p>Additionally, I have stored the consent letters for each team in the <code>./data</code> directory so that we can access them in our script like <code>./data/{final_id}.pdf</code>.</p>
<h2 id="heading-diving-into-the-script">Diving into the Script:</h2>
<h3 id="heading-1-centralized-configuration"><strong>1. Centralized Configuration</strong>:</h3>
<p>Instead of scattering configuration details across the code, we centralized them into a dictionary. This makes future updates or changes more manageable.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Centralized Configuration</span>
CONFIG = {
    <span class="hljs-string">"xsrf_token"</span>: <span class="hljs-string">""</span>,
    <span class="hljs-string">"csrf_token"</span>: <span class="hljs-string">""</span>,
    <span class="hljs-string">"larevel_token"</span>: <span class="hljs-string">""</span>,
    <span class="hljs-string">"input_file_path"</span>: <span class="hljs-string">"input_file.csv"</span>,
    <span class="hljs-string">"output_file_path"</span>: <span class="hljs-string">"response.csv"</span>,
    <span class="hljs-string">"url"</span>: <span class="hljs-string">"https://sih.gov.in/TeamRegistration"</span>,
    <span class="hljs-string">"team_member_count"</span>: <span class="hljs-number">6</span>
}
</code></pre>
<p><em>Having configurations centralized is always a good approach. It allows you to change settings without diving deep into the code, making it easier for future modifications or when moving the script to a different environment.</em></p>
<h3 id="heading-2-reading-the-csv"><strong>2. Reading the CSV</strong>:</h3>
<p>The team details were stored in a CSV. With the help of Python's <code>pandas</code> library, we read the data to be processed.</p>
<pre><code class="lang-python">df = pd.read_csv(CONFIG[<span class="hljs-string">"input_file_path"</span>])
</code></pre>
<p><em>Using pandas to handle CSV files not only simplifies the reading process but also makes data manipulation a breeze. With just a single line, we can load the entire CSV into a DataFrame.</em></p>
<h3 id="heading-3-extracting-students-year"><strong>3. Extracting Student's Year</strong>:</h3>
<p>We created a function to deduce the student's year from their roll number.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_student_year</span>(<span class="hljs-params">roll_number</span>):</span>
    enrollment_year_str = roll_number[:<span class="hljs-number">2</span>]
    year_mapping = {
        <span class="hljs-string">'23'</span>: <span class="hljs-string">'1st Year'</span>,
        <span class="hljs-string">'22'</span>: <span class="hljs-string">'2nd Year'</span>,
        <span class="hljs-string">'21'</span>: <span class="hljs-string">'3rd Year'</span>,
        <span class="hljs-string">'20'</span>: <span class="hljs-string">'4th Year'</span>
    }
    <span class="hljs-keyword">return</span> year_mapping.get(enrollment_year_str, <span class="hljs-string">""</span>)
</code></pre>
<p><em>While the code may seem trivial, this function ensures that the student's year is correctly extracted from their enrollment number. It's these small details that make our automation robust.</em></p>
<h3 id="heading-4-preparing-student-data"><strong>4. Preparing Student Data</strong>:</h3>
<p>To make the code more readable and maintainable, we split the data preparation into smaller chunks. Here, we focus on student-specific data.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">prepare_student_data</span>(<span class="hljs-params">row</span>):</span>
    student_data = {
        <span class="hljs-string">f"student_row[]"</span>: [],
        <span class="hljs-string">f"student_name[]"</span>: [],
        <span class="hljs-string">f"student_email[]"</span>: [],
        <span class="hljs-string">f"student_mobile[]"</span>: [],
        <span class="hljs-string">f"student_gender[]"</span>: [],
        <span class="hljs-string">f"student_stream[]"</span>: [],
        <span class="hljs-string">f"student_year[]"</span>: [],
    }

    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>, CONFIG[<span class="hljs-string">'team_member_count'</span>] + <span class="hljs-number">1</span>):
        member_name = row.get(<span class="hljs-string">f"member_<span class="hljs-subst">{i}</span>"</span>, <span class="hljs-string">""</span>)
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> member_name:
            <span class="hljs-keyword">continue</span>

        enrollment_year_str = row.get(<span class="hljs-string">f"member_<span class="hljs-subst">{i}</span>_enrollment"</span>, <span class="hljs-string">""</span>)[:<span class="hljs-number">2</span>]
        student_year = get_student_year(enrollment_year_str)
        gender = <span class="hljs-string">"Male"</span> <span class="hljs-keyword">if</span> row.get(<span class="hljs-string">f"member_<span class="hljs-subst">{i}</span>_gender"</span>, <span class="hljs-string">""</span>) == <span class="hljs-string">"M"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"Female"</span>

        student_data[<span class="hljs-string">f"student_row[]"</span>].append(i - <span class="hljs-number">1</span>)
        student_data[<span class="hljs-string">f"student_name[]"</span>].append(member_name)
        student_data[<span class="hljs-string">f"student_email[]"</span>].append(row.get(<span class="hljs-string">f"member_<span class="hljs-subst">{i}</span>_email"</span>, <span class="hljs-string">""</span>))
        student_data[<span class="hljs-string">f"student_mobile[]"</span>].append(str(row.get(<span class="hljs-string">f"member_<span class="hljs-subst">{i}</span>_mobile"</span>, <span class="hljs-string">""</span>)))
        student_data[<span class="hljs-string">f"student_gender[]"</span>].append(gender)
        student_data[<span class="hljs-string">f"student_stream[]"</span>].append(<span class="hljs-string">"B.Tech"</span>)
        student_data[<span class="hljs-string">f"student_year[]"</span>].append(student_year)

    <span class="hljs-keyword">return</span> student_data
</code></pre>
<p>*By modular</p>
<p>izing the data preparation, we can efficiently handle each team member's details without cluttering the main code.*</p>
<h3 id="heading-5-assembling-form-data"><strong>5. Assembling Form Data</strong>:</h3>
<p>Using the student data, we assembled the complete form data required for the POST request.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">prepare_form_data</span>(<span class="hljs-params">row</span>):</span>
    student_data = prepare_student_data(row)
    cookies = {<span class="hljs-string">"TOKEN"</span>: CONFIG[<span class="hljs-string">"xsrf_token"</span>], <span class="hljs-string">"laravel_session"</span>: CONFIG[<span class="hljs-string">"larevel_token"</span>]}

    form_data = {
        <span class="hljs-string">"_token"</span>: CONFIG[<span class="hljs-string">"csrf_token"</span>],
        <span class="hljs-string">"Team_name"</span>: row.get(<span class="hljs-string">"team_name"</span>, <span class="hljs-string">""</span>),
        <span class="hljs-string">"team_ctgry"</span>: row.get(<span class="hljs-string">"category"</span>, <span class="hljs-string">"Software"</span>),
        <span class="hljs-string">"team_status"</span>: row.get(<span class="hljs-string">"status"</span>, <span class="hljs-string">"waitlist"</span>),
        <span class="hljs-string">"team_type"</span>: <span class="hljs-string">"This team will compete for the problem statements listed on SIH 2023 portal"</span>,
        **student_data
    }

    file_path = <span class="hljs-string">f"./data/<span class="hljs-subst">{row.get(<span class="hljs-string">'final_id'</span>, <span class="hljs-string">''</span>)}</span>.pdf"</span>
    files = {
        <span class="hljs-string">"team_Registration_Consent_Letter"</span>: (
            os.path.basename(file_path),
            open(file_path, <span class="hljs-string">"rb"</span>),
        )
    }

    <span class="hljs-keyword">return</span> form_data, files, cookies
</code></pre>
<p><em>This function brings together various pieces of data into the format required by the SIH portal. It's essential to ensure that the data structure matches what the portal expects to avoid submission errors.</em></p>
<h3 id="heading-6-making-the-post-request"><strong>6. Making the POST Request</strong>:</h3>
<p>The <code>requests</code> library in Python does the heavy lifting, sending our prepared data to the SIH portal.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">make_post_request</span>(<span class="hljs-params">url, form_data, files, headers, cookies, attempt=<span class="hljs-number">1</span></span>):</span>
    <span class="hljs-keyword">try</span>:
        Team_name = form_data[<span class="hljs-string">"Team_name"</span>]
        logger.debug(<span class="hljs-string">f"SUBMITTING: <span class="hljs-subst">{Team_name}</span>"</span>)

        <span class="hljs-keyword">with</span> requests.post(url, data=form_data, files=files, headers=headers, cookies=cookies) <span class="hljs-keyword">as</span> response:
            response.raise_for_status()
            r = response.json()

            <span class="hljs-keyword">if</span> r[<span class="hljs-string">"MSG"</span>] == <span class="hljs-string">"Team Name Already Exists !"</span>:
                <span class="hljs-keyword">if</span> attempt &lt;= <span class="hljs-number">3</span>:
                    form_data[<span class="hljs-string">"Team_name"</span>] = form_data[<span class="hljs-string">"Team_name"</span>].lower().replace(<span class="hljs-string">" "</span>, <span class="hljs-string">"_"</span>) + <span class="hljs-string">"_"</span>
                <span class="hljs-keyword">else</span>:
                    logger.error(<span class="hljs-string">f"TOO MANY ATTEMPTS: (NAME EXISTS) -&gt; <span class="hljs-subst">{Team_name}</span>"</span>)
                    <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>

                time.sleep(<span class="hljs-number">3</span>)
                make_post_request(url, form_data, files, headers, cookies, attempt=attempt + <span class="hljs-number">1</span>)
            <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
    <span class="hljs-keyword">except</span> requests.RequestException <span class="hljs-keyword">as</span> e:
        logger.exception(<span class="hljs-string">f"Error making POST request. Error: <span class="hljs-subst">{e}</span>"</span>)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
</code></pre>
<p><em>This function is the heart of our automation. It attempts to register each team on the portal and handles cases where the team name might already exist.</em></p>
<h3 id="heading-7-processing-and-logging"><strong>7. Processing and Logging</strong>:</h3>
<p>We processed each row from our CSV, logged our progress, and captured any issues that arose. Logging is crucial as it helps monitor the script's progress and diagnose issues.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_dataframe</span>(<span class="hljs-params">df</span>):</span>
    headers = {<span class="hljs-string">"X-CSRF-TOKEN"</span>: CONFIG[<span class="hljs-string">"csrf_token"</span>]}

    <span class="hljs-keyword">for</span> index, row <span class="hljs-keyword">in</span> df.iterrows():
        form_data, files, cookies = prepare_form_data(row)
        success = make_post_request(CONFIG[<span class="hljs-string">"url"</span>], form_data, files, headers, cookies)

        <span class="hljs-comment"># Close the file after making a request</span>
        files[<span class="hljs-string">"team_Registration_Consent_Letter"</span>][<span class="hljs-number">1</span>].close()
        df.at[index, <span class="hljs-string">"success"</span>] = success
        logger.debug(<span class="hljs-string">f"Row <span class="hljs-subst">{index}</span>, success: <span class="hljs-subst">{success}</span>"</span>)

        time.sleep(<span class="hljs-number">10</span>)
    <span class="hljs-keyword">return</span> df
</code></pre>
<p><em>Proper logging ensures we have a complete trace of the script's actions. This is invaluable for debugging and verifying the results.</em></p>
<h3 id="heading-8-execution"><strong>8. Execution</strong>:</h3>
<p>Finally, we assembled all these pieces in the main execution function.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    df = pd.read_csv(CONFIG[<span class="hljs-string">"input_file_path"</span>])

    <span class="hljs-keyword">try</span>:
        df = process_dataframe(df)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        logger.exception(<span class="hljs-string">f"Error processing DataFrame. Error: <span class="hljs-subst">{e}</span>"</span>)
    <span class="hljs-keyword">finally</span>:
        df.to_csv(CONFIG[<span class="hljs-string">"output_file_path"</span>], index=<span class="hljs-literal">False</span>)
        logger.debug(<span class="hljs-string">f"DataFrame saved to <span class="hljs-subst">{CONFIG[<span class="hljs-string">'output_file_path'</span>]}</span>"</span>)
</code></pre>
<p><em>The main function brings everything together, orchestrating the whole registration process from start to finish.</em></p>
<h3 id="heading-9-logging"><strong>9. Logging</strong>:</h3>
<p>Logging was set up to capture all details and errors during the process. This helps in debugging and ensuring all teams were registered correctly.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Set up logging</span>
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

<span class="hljs-comment"># Create a file handler</span>
handler = logging.FileHandler(<span class="hljs-string">"team_registration.log"</span>)
handler.setLevel(logging.DEBUG)

<span class="hljs-comment"># Create a console handler</span>
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)

<span class="hljs-comment"># Create a logging format</span>
formatter = logging.Formatter(<span class="hljs-string">"%(asctime)s - %(name)s - %(levelname)s - %(message)s"</span>)
handler.setFormatter(formatter)
console_handler.setFormatter(formatter)

<span class="hljs-comment"># Add the handlers to the logger</span>
logger.addHandler(handler)
logger.addHandler(console_handler)
</code></pre>
<p><em>Proper logging is invaluable in any automation script. It provides insights into the script's workings and can be a lifesaver when troubleshooting issues.</em></p>
<h2 id="heading-speeding-things-up">Speeding Things Up:</h2>
<p>Now, while the above solution works, it operates in a serial manner. Making HTTP requests is essentially IO time that the CPU is waiting for. How about speeding things up?</p>
<h3 id="heading-parallel-processing-with-subprocess">Parallel Processing with <code>subprocess</code>:</h3>
<p>Python's <code>subprocess</code> library allows us to spawn new processes. By dividing our input data into chunks, we can assign each chunk to a separate subprocess. This would allow us to make multiple POST requests simultaneously, significantly reducing the overall time.</p>
<p>However, this brings up two challenges:</p>
<ol>
<li>Handling <code>response.csv</code> for multiple processes.</li>
<li>Ensuring proper logging from all subprocesses.</li>
</ol>
<p><strong>Solution</strong>:</p>
<ol>
<li>Instead of a single <code>response.csv</code>, each subprocess can write to a separate CSV file. Later, these can be merged.</li>
<li>The logger can be set up to include the subprocess ID in the log messages, helping us trace logs from different subprocesses.</li>
</ol>
<h3 id="heading-1-using-subprocess-to-spawn-new-processes"><strong>1. Using <code>subprocess</code> to Spawn New Processes</strong>:</h3>
<p>The <code>subprocess</code> module in Python allows us to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. To utilize this, we can create a new script dedicated to handling a chunk of our data and then call this script multiple times in parallel.</p>
<p>Here's a simple example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> subprocess

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">spawn_process</span>(<span class="hljs-params">script_name, input_file</span>):</span>
    process = subprocess.Popen([<span class="hljs-string">"python"</span>, script_name, input_file])
    <span class="hljs-keyword">return</span> process

<span class="hljs-comment"># Example usage</span>
processes = []
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(number_of_chunks):
    p = spawn_process(<span class="hljs-string">"handle_chunk.py"</span>, <span class="hljs-string">f"chunk_<span class="hljs-subst">{i}</span>.csv"</span>)
    processes.append(p)

<span class="hljs-comment"># Wait for all processes to complete</span>
<span class="hljs-keyword">for</span> p <span class="hljs-keyword">in</span> processes:
    p.wait()
</code></pre>
<h3 id="heading-2-handling-separate-response-files"><strong>2. Handling Separate Response Files</strong>:</h3>
<p>As mentioned, each subprocess can write its results to a separate CSV file. After all processes are done, we can merge these files into one consolidated response file.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">merge_csvs</span>(<span class="hljs-params">file_list, output_file</span>):</span>
    df_list = [pd.read_csv(file) <span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> file_list]
    merged_df = pd.concat(df_list, ignore_index=<span class="hljs-literal">True</span>)
    merged_df.to_csv(output_file, index=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Example usage</span>
file_list = [<span class="hljs-string">f"response_chunk_<span class="hljs-subst">{i}</span>.csv"</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(number_of_chunks)]
merge_csvs(file_list, <span class="hljs-string">"final_response.csv"</span>)
</code></pre>
<h3 id="heading-3-logging-with-subprocess-id"><strong>3. Logging with Subprocess ID</strong>:</h3>
<p>To ensure each subprocess logs uniquely, we can modify our logging setup:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

<span class="hljs-comment"># Set up logging</span>
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

<span class="hljs-comment"># Create a file handler</span>
handler = logging.FileHandler(<span class="hljs-string">f"team_registration_<span class="hljs-subst">{os.getpid()}</span>.log"</span>)
handler.setLevel(logging.DEBUG)

<span class="hljs-comment"># ... rest of the logging setup remains the same</span>
</code></pre>
<p>By using <code>os.getpid()</code>, each subprocess will have a unique log file based on its process ID.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong>:</h2>
<p>Automation can transform tedious tasks into swift, error-free processes. With just a simple Python script, our College SPOC bypassed hours of manual data entry, ensuring timely and accurate registrations.</p>
<p>Remember: Always look for automation opportunities. As developers, our time is best spent solving problems, not doing repetitive tasks.</p>
<hr />
<p>Happy coding, and may you always find ways to "Automate the boring stuff!" If you have questions or suggestions, drop them in the comments below!</p>
<h2 id="heading-appendix-extracting-tokens-from-the-browser"><strong>Appendix: Extracting Tokens from the Browser</strong></h2>
<p>For our script to work smoothly, it's essential to extract certain authentication tokens directly from the browser. If you're unfamiliar with this process, don't worry! This section will guide you step by step.</p>
<h3 id="heading-preliminary-step-logging-in"><strong>Preliminary Step: Logging In</strong></h3>
<p>Before you begin extracting tokens, ensure you are logged into the SIH portal. The tokens we need are generated post-login.</p>
<h3 id="heading-1-extracting-xsrftoken-and-laraveltoken-from-cookies"><strong>1. Extracting <code>xsrf_token</code> and <code>laravel_token</code> from Cookies</strong>:</h3>
<ul>
<li>Once logged in, open the SIH portal in your browser.</li>
<li>Right-click anywhere on the page and select 'Inspect' or 'Inspect Element' to open the browser's developer tools.</li>
<li>Navigate to the 'Application' tab.</li>
<li>In the left sidebar, under the 'Cookies' section, click on the SIH portal's URL.</li>
<li>Here, you'll find a list of cookies. Look for <code>xsrf_token</code> and <code>laravel_token</code>.</li>
<li>Before copying the token value, ensure you toggle on 'Show URL-encoded' (usually found at the bottom of the cookies panel).</li>
<li>Copy the respective values of <code>xsrf_token</code> and <code>laravel_token</code>.</li>
</ul>
<p><img src="https://res.cloudinary.com/dib9srrul/image/upload/v1697085925/blog/yi6zu1esbtgo31lnrt7n.png" alt="Image" />
<img src="https://res.cloudinary.com/dib9srrul/image/upload/v1697086345/blog/mnpxhymzgyi6xatkz4tz.png" alt="Image" /></p>
<h3 id="heading-2-extracting-csrftoken-from-meta-tags"><strong>2. Extracting <code>csrf_token</code> from Meta Tags</strong>:</h3>
<ul>
<li>While still on the SIH portal page, navigate to the 'Elements' tab in the developer tools.</li>
<li>Here, you'll see the source HTML of the page. Look for meta tags (usually near the top).</li>
<li>Find the meta tag with the attribute <code>name</code> set to <code>csrf-token</code>.</li>
<li>Copy the content value of this meta tag, which is your <code>csrf_token</code>.</li>
</ul>
<p><img src="https://res.cloudinary.com/dib9srrul/image/upload/v1697086671/blog/rydrdqmpfhkmsncwjet1.png" alt="Image" /></p>
<p><em>Please refer to the attached screenshots for a visual guide on extracting these tokens.</em></p>
<hr />
<p><em>Note: Always ensure you're using up-to-date tokens, as they may expire or change over time. If the script fails to authenticate, re-extract the tokens and try again.</em></p>
]]></content:encoded></item></channel></rss>