<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>پست‌های انتشارات اینترنردز</title>
        <link>https://virgool.io/internerds/feed</link>
        <description>یعنی کسایی که دائما توی اینترنت می‌چرخند!</description>
        <language>fa</language>
        <pubDate>2026-04-15 10:17:48</pubDate>
        <image>
            <url>https://files.virgool.io/upload/publication/a8wcppzorwj9/zvgedp.png</url>
            <title>اینترنردز</title>
            <link>https://virgool.io/internerds</link>
        </image>

                    <item>
                <title>چای ۱۲: فرمت‌دهی ویدئو برای Video Strickerهای تلگرام با استفاده از FFmpeg</title>
                <link>https://virgool.io/internerds/tea-12-format-tg-video-sticker-using-ffmpeg-adyyqpqlsqfv</link>
                <description>مقدمهتلگرام (Telegram) در آخرین بروزرسانی اخیرش، یکی از معدود ویژگی‌هایی که از رقیب نه‌چندان قدر ولی پرطرفدارش واتس‌اپ (Whatsapp) کمتر داشت رو جبران کرد و پشتیبانی از استیکر‌های ویدئویی (Video Sticker) رو اضافه کرد.استیکرهای ویدئویی، تصاویر متحرک بدون صدایی با فرمت فایل WEBM هستند که مثل استیکر‌های معمولی و استیکر‌های انیمیشنی (Animated Sticker) به‌صورت پک دسته‌بندی شده و ذخیره می‌شوند.نمونه‌ای از یک استیکر ویدئویی -به پیکسلی بودن تصویر توجه کنید.تفاوت با GIFهابرخلاف گیف‌ها (جیف [GIF])، استیکرهای ویدئویی از لایه شفاف (Transparent) در تصویر پشتیبانی کرده (VP9 Codec) و بر اساس تنظیمات انکودینگ (Encoding) تصویر می‌توانند حجم کمتری داشته باشند.تفاوت با Animated Stickerهااستیکرهای انیمیشنی تصاویری برداری (وکتوری [Vector]) با فرمت فایل TGS هستند که با استفاده از تکنولوژی Lottie تولید شده و نمایش داده می‌شوند. برای تولید آن‌ها با استفاده از برنامه Adobe After Effect و با کمک شاخه‌ای از افزونه Bodymovin، تصاویر متحرک به فرمت مخصوص Lottie (فرمتی در قالب JSON) تبدیل شده و سپس به فرمت فایل TGS تبدیل می‌شوند.اما استیکر‌های ویدئویی پیچیدگی کمتری داشته و تصاویری پیکسلی (رستری [Raster]) هستند -همانند فیلم‌هایی کوتاه و بدون صدا- که فرمت فایل WEBM و کدک (Codec) VP9 ذخیره شده‌اند.آشنایی با FFmpegدر خلاصه‌ترین حالت، FFmpeg یک کتاب‌خانه، فریم‌ورک و مجموعه‌ای از برنامه‌های تحت خط فرمان (CLI)   چندسکویی (Cross-Platform) با امکانات فراوان برای نمایش، تبدیل، تغییر و ویرایش در ویدئوها و تصاویر (و تقریبا هر فرمت نمایش اطلاعات دیگری) است که به‌صورت متن‌باز توسعه و به‌صورت رایگان ارائه می‌شود. در این پست با استفاده از رابط خط فرمان FFmpeg یک ویدئو با فرمت mp4 را به فرمت مربوطه تبدیل می‌کنیم.پیشنهادImageMagick ابزار تحت خط فرمان دیگری برای کار با تصاویر است که پیش از این در پست زیر اون رو بررسی کردم:آشنایی با ImageMagick برای کار با تصاویراستفاده از رابط خط فرمان FFMPEG بسیار ساده بوده و قالب اجرای دستورات با استفاده از دستور ffmpeg --help قابل مشاهده است:$ ffmpeg --help
usage: ffmpeg [options] [[infile options] -i infile] ... {[outfile options] outfile}...نصببرای تصب FFmpeg بر اساس پلتفرم و سیستم خود یکی از روش‌های زیر را استفاده کنید:ویندوز# Download the zip file
https://github.com/BtbN/FFmpeg-Builds/releases

# using chocolatey package manager
choco install ffmpegاطلاعات بیشترلینوکس# Ubuntu
sudo apt install ffmpeg

# Arch
pacman -S ffmpegاطلاعات بیشترپیش‌نیازهای استیکر‌های ویدئویی (Video Sticker)برای اطلاعات بیشتر مستندات انکودینگ (Encoding) را مرور کنید.یکی از اضلاع (طول یا عرض) ویدئو باید دقیقا ۵۱۲ پیکسل باشد - ضلع دیگر می‌تواند ۵۱۲ پیکسل یا کمتر باشد.طول ویدئو باید کمتر از ۳ ثانیه باشد.فریم ریت تصویر می‌تواند تا ۳۰ فریم بر ثانیه (30FPS) باشد.ویدئو باید یک لایه شفاش (Transparent) داشته باشد (طبق گفته مستندات این مورد موقتی‌ست).سایز ویدئو نباید از ۲۵۶ کیلوبایت (256KB) تجاوز کند.ویدئو باید در فرمت WEBM باشد و توسط کدک VP9 انکود (Encode) شده باشد.ویدئو نباید هیچ کانال صوتی داشته باشد (بدون صدا باشد).بهتر است ویدئو تکرار شوند باشد تا تجربه کاربری بهتری ایجاد کند.فرمت‌دهی ویدئو توسط FFmpegبرای فرمت‌دهی ویدئو به فرمت مورد نیاز می‌توانیم از دستور زیر استفاده کنیم:ffmpeg -i video.mp4 -c:v vp9 -pix_fmt yuva420p -b:v 1M -vf &amp;quotfps=30,scale=512:-1&amp;quot -an video.webmتوضیح تنظیمات دستور (Flags)- ‏i | اجباری | آدرس(های) فایل ورودی- ‏‏c:v | اجباری | تنظیم کدک؛ کدک VP9 از کانال آلفا (Alpha Channel) برای شفایت تصویر (Transparency) پشتیبانی می‌کند. - ‏pix_fmt | اجباری | فرمت پیکسل‌ها؛ فرمت yuva420p برای پشتبانی از کانال آلفا لازم است.- ‏b:v | اختیاری | تنظیمات بیت ریت ویدئو- ‏vf | اختیاری | تنظیمات فیلترهای ویدئو؛ استفاده از fps=30 برای تعیین فریم ریت ویدئو.- ‏vf | اجباری | تنظیمات فیلترهای ویدئو؛ استفاده از scale برای مشخص کردن ابعاد تصویر دیدئوی خروجی (در اینجا طول ویدئو ۵۱۲ پیکسل تعیین شده و عرض ویدئو بر اساس نسبت تصویر به‌صورت خودکار تعیین خواهد شد).- ‏an | اختیاری | تعیین بدون صدا بودن ویدئو خروجی. اگر ویدئوی ورودی بدون صداست نیازی به استفاده نیست.منابعمستندات استیکرهای تلگراماطلاعات کدک VP9 در مستندات FFmpegاین بلاگ پست عالی با عنوان «Alpha Masking with FFMPEG»این پست، قسمت دوازدهم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه‌ی این کار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Thu, 03 Feb 2022 16:39:25 +0330</pubDate>
            </item>
                    <item>
                <title>چای ۱۱: حل مشکل نگاشت پورت‌های WSL 2</title>
                <link>https://virgool.io/internerds/tea-11-wsl2-portforwarding-hv7xtv3fvkxt</link>
                <description>مقدمه‏Windows Subsystem for Linux یا به اختصار WSL به توسعه‌دهندگان اجازه میده تا یک محیط GNU/Linux  رو بدون سربار ماشین‌های مجازی به‌صورت مستقیم روی ویندوز اجزا کنن. اجرای دستورات و برنامه‌های بر پایه POSIX روی ویندوز ویژگی‌ای‌ست که مایکروسافت مدت زیادی به دنبال آن بوده و بعد از فراگیر شدن روش‌های ایزوله‌سازی و کانتیر کردن سیستم‌ها (containerization) و لزوم به اجرای داکر (Docker) روی ویندوز و در نتیجه تغییر رویکردهای مایکروسافت، به‌صورت جدی‌تر دنبال شد.نسخه اولیه WSL در سال ۲۰۱۶ به‌عنوان یک لایه رابط کرنل (Kernel Interface) و بدون هیچ کرنل لینوکسی، پس از تلاش‌های ویندوز برای توسعه Hyper-V ظاهر شد که اجازه اجرای یک فضای کاربری* برپایه GNU مانند ابونتو (Ubuntu)‌ را می‌داد [۱].نسخه دوم WSL در سال ۲۰۱۹ با تغییراتی در معماری (همراه با ادغام Hyper-V داخل ویندوز) معرفی‌شد و یک کرنل واقعی لینوکس است که روی یک ماشین‌مجازی خیلی سبک اجرا می‌شود. در این نسخه، همچنین دسترسی به شبکه و دسترسی مشترک به فضای کاری ویندوز و لینوکس (فایل‌ها و برنامه‌ها) بهبودهای چشمگیری داشته و فرآیند نصب و فعال‌سازی نیز بسیار ساده شده‌‌ست. اخیرا و در آخرین بیلدهای (Build) ویندوز ۱۰ و در ویندوز ۱۱، با معرفیِ پشتیبانی از GPU و همچنین WSLg، برنامه‌های لینوکسی می‌توانند از شتاب‌دهنده‌های سخت‌افزاری بهره‌برده و یا برنامه‌های دارای رابط کاربری گرافیکی (GUI)، در کنار برنامه‌های ویندوزی اجرا شده و قابل دسترس باشند [۱].می‌توانید شرح تفاوت‌ها و تغییرات بین WSL1 و WSL2 را در مستندات WSL بخوانید.برای تجربه WSL اگر از نسخه‌های بروز ویندوز ۱۰ و یا ویندوز ۱۱ استفاده می‌کنید، ابتدا از دستور زیر برای راه‌اندازی کرنل استفاده کنین و سپس از Microsoft Store یک توزیع لینوکسی از بین توزیع‌های موجود را نصب کنید.  همین!wsl --installمشکل نگاشت پورت‌ها (Port Forwarding)در کنار ویژگی‌های بی‌نظیر WSL و انعطاف‌پذیری و دسترسی‌پذیری‌ای که برای توسعه‌دهندگان بوجود میاره، مشکلات جزئی* کمی هم داره که یکی از اون‌ها مشکلاتی در مسیریابی پورت‌ها به‌خصوص هنگام دسترسی به سرور‌های محلی (Local Servers) اجرا شده، از سمت ویندوز است.با اجرای یک برنامه‌ی تحت شبکه، برای مثال اجرای یک سرور روی WSL، باید بتوان از سمت ویندوز و از طریق شبکه داخلی (localhost) به آن‌ها دسترسی داشت (شبکه باید یک شبکه خصوصی [Private] باشد). این اتفاق به‌صورت خودکار در WSL1 انجام می‌شد، اما متأسفانه رفتار پیش‌فرض در WSL2 این نیست [۳].از آنجایی که WSL2 از یک آداپتور مجازی (Virtual Network Adapter) برای اتصال به شبکه استفاده می‌کند، با هربار ورود به ویندوز و اجرای اولیه WSL، کرنل یک IP جدید در شبکه داخلی، مانند IP زیر دریافت می‌کند [۳]:❯ hostname -I
172.31.6.171سرور‌های اجرا شده در WSL از این آدرس در دسترس هستند،‌ اما همانطور که اشاره شد این آدرس هربار تغییر کرده و نیاز داریم تا با استفاده از localhost ویندوز، مانند آدرس زیر، بتوانیم به آن‌ها دسترسی داشته باشیم.localhost:8080این مشکل در هربار بوت شدن ویندوز اتفاق نمی‌افتد؛ اما با این حال به دلیل اینکه حتی با ری‌استارت کردن  WSL2 و یا خاموش کردن فایروال (Firewall) ویندوز این مشکل رفع نمی‌شود، باعث می‌شود در کارکرد WSL2 عدم قطعیت ایجاد کرده و آن را مختل کند [۲].یکی از دلایل احتمالی این اتفاق -همانطور که در این issue به آن اشاره شده- به‌دلیل روشن‌بودن تنظیم Fast Startup است، با این‌حال به‌دلیل اینکه شخصاً علاقه‌ای به خاموش‌کردن این گزینه نداشتم، به دنبال راه‌حل دیگری بودم.لازم به ذکر است می‌توانید برای خاموش‌کردن WSL، دستور زیر را در CMD یا PowerShell ویندوز اجرا کنید:# PowerShell 
PS C:\Users\[username]&gt; wsl --shutdownرفع مشکل نگاشت پورت‌هابرای رفع این مشکل، باید همانطور که در مستندات WSL توضیح داده شده، پورت‌های لازم را به WSL نگاشت یا فوروارد کنیم (Port Forwarding) که برای سهولت کار و خودکار‌سازی آن، از ابزار netsh استفاده می‌کنیم.برای اینکار یک فایل با فرمت ps1 (برای مثال wsl2-port-forwarding.ps1) ساخته و اسکریپت زیر را در آن کپی کنید [۲ و ۳]:در صورت عدم نمایش:  gist.github.com/mhsattarian/bb55026b1e34cf8357c37289d693cec4 https://gist.github.com/mhsattarian/bb55026b1e34cf8357c37289d693cec4 این اسکریپت برای اجرا نیاز به دسترسی Admin داشته (به‌اصطلاح Elevated Permissions) و در ابتدا برای دریافت این دسترسی‌ها درخواستی فراخوانی می‌کند. سپس آدرس IP فعلی WSL2 را دریافت کرده و با استفاده از دستور netsh پورت‌های مشخص‌شده در آرایه ports$ را به این آدرس فوروارد (نگاشت) می‌کند. در کنار این کار قوانین نامرتبط در فایروال را نیز حذف می‌کند [۲ و ۳].می‌توانید با تغییر آرایه ports$، پورت‌های دلخواه خودتون رو مشخص کنید. بدین‌صورت برنامه‌ها و سرورهای اجرا شده در WSL2 از طریق localhost در ویندوز قابل دسترسی خواهند بود. در نهایت می‌توانید برای مشاهده پورت‌های فوروارد شده از دستور زیر استفاده کنید [۳]:netsh interface portproxy show v4tov4اجرای خودکار اسکریپتبا هربار اجرای اسکریپت بالا تنظیمات نگاشت پورت‌ها به درستی تنظیم (Set) شده و برنامه‌ها و سرور‌های WSL2 از طریق localhost در ویندوز در دسترس خواهند بود. بااین‌حال، اجرای اسکریپت هربار که WSL به مشکل می‌خورد شاید چندان راحت یا مقبول نباشد؛ برای سهولت بیشتر می‌توان با استفاده از Task Scheduler ویندوز این اسکریپت را در هربار بوت سیستم اجرا کنیم [۲].برای اینکار وارد Task Scheduler شده و از منوی سمت راست روی Create Task کلیک کنید؛ در پنجره‌ی باز شده یک نام برای این تسک مشخص کرده و وارد تب Triggers شوید، روی گزینه New کلیک کرده و زمان اجرای تسک را برابر At startup قرار دهید. پیشنهاد میشه برای تأخیرِ (Delay) اجرای تسک نیز مقداری (مثلاً ۳۰ ثانیه) را مشخص کنید:مشخص کردن زمان اجرای تسک در تب Triggersسپس وارد تب Actions شده و روی گزینه New کلیک کنید. به‌عنوان برنامه‌ای که باید اجرا شود به‌صورت زیر PowerShell ویندوز را مشخص کنید:Powershell.exeبه‌عنوان آرگومان‌ها به‌صورت زیر، آدرس اسکریپت را به‌همراه فلگ ExecutionPolicy- با مقدار Bypass وارد کنید:C:\Users\[username]\[path_to_script]\wsl2-port-forwarding.ps1 -ExecutionPolicy Bypassمشخص کردن برنامه اجرا شده در تب Actionsاگر از لپتاپ استفاده می‌کنید و در صورت امکان در تب Conditions تیک گزینه زیر را بردارید تا تسک زمانی که لپتاپ درحال شارژ نیست نیز اجرا شود:تنظیم اجرای تسک در زمان استفاده از باتری داخلی لپتاپبا زدن گزینه‌ی OK این تسک را ذخیره کنید. بدین‌صورت با هربار بوت ویندوز این تسک اجرا شده و دیگر نیازی به اجرای دستی آن نیست.پانویس*فضای کاربری: یک سیستم‌عامل مدرن، معمولاً حافظه‌ی مجازی را به دو بخش فضای هسته و فضای کاربری مجزا می‌کند. در اینجا منظور از فضای کاربری یک سیستم عامل لنوکسی (تعدیل شده) بدون کرنل لینوکس است.*مشکلات جزئی WSL: دیگر مشکلاتی که برخوردم شامل، اجرا نشدن WSL بعد از فراخوانی‌ست که با ری‌استارت WSL درست شده و مشکل دیگر آزاد نشدن رم اشغال شده توسط WSL پس از پایان یک پردازش (Process) است که طبق وعده‌های مایکروسافت در آپدیت‌های آینده باید رفع شود.منابع[۱] صفحه ویکی‌پدیا Windows Subsystem for Linux[۲] کامنت‌های issueهای ریپازیتوری WSL در گیت‌هاب (Github)[۳] این پست با موضوع مشابه در dev.toاین پست، قسمت یازدهم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه‌ی این کار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Sun, 24 Oct 2021 19:12:17 +0330</pubDate>
            </item>
                    <item>
                <title>چای ۱۰: رفع مشکل No Audio Output Device</title>
                <link>https://virgool.io/internerds/%DA%86%D8%A7%DB%8C-%DB%B1%DB%B0-%D8%B1%D9%81%D8%B9-%D9%85%D8%B4%DA%A9%D9%84-no-audio-output-device-uwa19wmik89d</link>
                <description>یه مشکل دردناکی چندباری برای لپتاپم پیش اومد که دلیلش رو نمی‌دونم و اینجوری هست که یهو تمامی درایورها و خروجی‌های صوتی  لپتاپ از بین میرن. یعنی دیگه نمیشه هیچ صدایی شنید، نه با اسپیکر نه با هدفون، با هیچ‌چیزی... مشکل هم از درایور و اینا نیست چون تمامی راهکارهای موجود در یوتیوب و نتایج سرچ گوگل و stack exchange رو امتحان کردم و جواب نداده بود. بار اول که این مشکل پیش اومد نهایتاً با Reset کردن ویندوز مشکل حل شد اما خب مجبور بودم که نرم‌افزارهای قبلی که داشتم رو دوباره نصب کنم. دفعه‌ی دوم هم چون از دفعه‌ی قبل فهمیده بودم هیچ راه‌حلی نداره، یه Restore Point بعد نصب همه‌ی نرم‌افزارها درست کرده بودم و با بازگردانی اون مشکل حل شد. اما، بار دیگه دو روز پیش این مشکل پیش اومد و این بار ری‌استور پوینت قبلی برای خیلی وقت پیش بود... منم کلاً یادم رفته بود اون رو آپدیت کنم این شد که دوباره کل وب رو گشتم و همون آش و همون کاسه. راستش می‌دونستم مشکل از رجیستریه ولی نمی‌دونستم چیکار باید بکنم. نزدیک‌ترین راه‌حل، به چیزی که آخر سر مشکلم رو حل کرد، یافتم این پست هست. اما میگم این هم مشکل من رو حل نکرده بود... توی این پست میاد تغییری که توی مقدار یکی از متغیرهای مربوط به Audio‌ی سیستم ایجاد شده رو از توی رجیستری حذف می‌کنه، ولی نکته‌ی داستان برای من توی حذف کل محتوای این متغیر بود. حالا خواستم توی یه پست بگم که اگه شما هم به این مشکل خوردین و دیگه هیچ امیدی نداشتین این کار رو بکنید. راستی من از ویندوز ۱۰ ورژن ۱۹۰۹ استفاده می‌کنم و لپتاپم هم HP هست. مراحل رو در ادامه توضیح میدم.۱- مشکلی که می‌گم این هست:عکس رو از گوگل پیدا کردم.۲- خب کاری که باید برای رفع این مشکل بکنید این هست که Registry Editor رو باز کنید (برای این کار می‌تونید این عبارت رو توی منوی استارت بنویسید یا اینکه عبارت Regedit رو توی Run وارد کنید). بعد به مسیر زیر برید:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96C-E325-11CE-BFC1-08002BE10318}عکس از همون پستی که لینکش رو گذاشتم داخل متن۳- مقدار متغیر UpperFilters رو پاک کنید (برای این‌کار روش کلیک بکنید و در پنجره‌ی باز شده عبارت موجود رو پاک کنید).این پست، قسمت هشتم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه‌ی این کار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسین ستاریان</author>
                <pubDate>Fri, 14 May 2021 21:08:14 +0430</pubDate>
            </item>
                    <item>
                <title>چای ۹: تبدیل GeoJSON به SVG با استفاده از D3</title>
                <link>https://virgool.io/internerds/geojson-2-svg-ykbcx12vjdot</link>
                <description>مقدمهجئوجیسون (GeoJSON) یک فرمت ذخیره‌سازی و نمایش اطلاعات جغرافیایی (به همراه خصوصیات غیر برداری) برپایه فرمت JSON است که در برنامه‌ها و سیستم‌های مرتبط با اطلاعات جغرافیایی استفاده زیادی دارد.حتی دیتابیس‌هایی مثل mongoDB از این فرمت منحصرا پشتیبانی کرده و از از یک داده JSON عادی متمایز می‌کنند.این فرمت از داده‌های جغرافیایی مختلفی مثل نقطه (Point)، خط (LineString)، پولیگان (Polygon) و مجموعه‌هایی از آن‌ها -مثلا MultiPoint- پشتیبانی می‌کنه که در GeoJSON RFC تبیین شدن.یک نمونه ساده از یک نقطه به‌فرمت  GeoJSON به‌صورت زیر است:نمایش یک نمونه GeoJSON در سایت geojson.io برای نمایش بصری داده‌های جغرافیایی‌ از روش‌های مختلفی استفاده می‌شود، این داده‌ها را می‌توان به‌صورت تایل (کاشی [Tile]) شده و یا به‌صورت واحد، به فرمت‌های مختلف تصویر رستری (پیکسلی [raster])‌ یا وکتوری (برداری [vector]) نمایش داد. در این پست می‌خواهیم داده‌های جغرافیایی به فرمت GeoJSON رو به‌فرمت SVG که یکی از روش‌های مرسوم نمایش داده‌های گرافیکی -عموما تصاویر- و یکی از انعطاف‌پذیر‌ترین، کم‌حجم‌ترین و دردسترس‌ترین فرمت‌های استفاده شده در وب است تبدیل کنیم.آماده‌سازیبرای این تبدیل از کتاب‌خونه D3 استفاده می‌کنیم و نیاز به یک محیط اجرای جاوا اسکریپت (Javascript) داریم که بتونیم توسط اون به DOM هم دسترسی داشته باشیم. بنابراین اگر از NodeJS برای این تبدیل استفاده می‌کنید یکی از پکیج‌های پیاده‌ساز DOM مثل jsdom و یا پکیجی مانند d3-node را استفاده کنید.داده‌های GeoJSONبرای ساخت یک داده جغرافیایی به فرمت GeoJSON ابزار‌های حرفه‌ای زیادی مانند نرم‌افزار QGIS وجود دارن، اما برای سادگی‌کار از ابزار آنلاین geojson.io ساخت شرکت mapbox استفاده می‌کنیم. این سایت رو باز کنید و با استفاده از نوار ابزار سمت راست یک یا چند شکل (نقطه یا پولیگان یا غیره) رسم کنید:رسم یک پولی‌گان (Polygon) در geojson.ioتبدیل GeoJSON به SVGابتدا با استفاده از D3 یک SVG به سایز مورد نظرمون می‌سازیم:const width = 200;
const height = 100;

const svg = d3
  .create(&amp;quotsvg&amp;quot)
  .attr(&amp;quotwidth&amp;quot, width)
  .attr(&amp;quotheight&amp;quot, height);قبل از تبدیل کد GeoJSON به یک تصویر SVG، نکته مهمی رو لازم است بدونیم:مختصات نقاط در فرمت GeoJSON به‌صورت پادساعت‌گرد ذخیره می‌شوند، درحالی‌که، D3 به‌صورت پیش‌فرض، یک عارضه‌را به‌صورت ساعت‌گرد انتظار داشته و در‌نظر می‌گیرد.برای اینکه مختصات پولیگان خودمون رو به‌صورت ساعت‌گرد تبدیل کنیم، از ابزار mapbox/geojson-rewind استفاده می‌کنیم:const _geoJson = rewind(polygon, true);حال برای نمایش عارضه GeoJSON و تبدیل اون به SVG از d3-geo استفاده می‌کنیم که به‌صورت پیش‌فرض داخل D3 موجوده ولی به‌صورت یک کتابخانه جدا نیز ارائه میشه. برای اینکار کافیه تا با استفاده از d3.geoPath یک تابع path ایجاد کنیم و از آن در ساخت المان path داخل SVG خودمون استفاده کنیم.با اینکه با استفاده از این روش فایل GeoJSON ما به‌درستی به SVG تبدیل شده، سایز نمایش اون درست نیست و درواقع کل محدوده مختصات جغرافیایی (کل نقشه جهان) به محدوده SVG ما نگاشت شده و در نتیجه پولیگان رسم‌شده بسیار کوچک خواهد بود.برای اینکه بتونیم پولیگان را به اندازه فعلی SVG تصویر کنیم و به‌اصطلاح project کنیم به‌صورت زیر عمل می‌کنیم:پولیگان تبدیل شده درحالت‌های تصویر نشده و تصویر شده به سایز SVGدر این روش، مختصات تبدیل شده توسط سیستم تصویر مرکاتور (سیستمی برای نمایش نقشه جهان به‌صورت تخت) را به‌سایز فعلی SVG متناسب می‌کنیم.نتیجه نهایی رو می‌تونید در مثال زیر مشاهده کنید: https://stackblitz.com/edit/geojson-svg-d3?embed=1&amp;file=index.js&amp;hideExplorer=1 این پست، قسمت نهم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه‌ی این کار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Sat, 17 Oct 2020 20:10:18 +0330</pubDate>
            </item>
                    <item>
                <title>چای ۸: بریدن و چسباندن ویدیو‌ها بدون خونریزی</title>
                <link>https://virgool.io/internerds/%DA%86%D8%A7%DB%8C-%DB%B8-%D8%A8%D8%B1%DB%8C%D8%AF%D9%86-%D9%88-%DA%86%D8%B3%D8%A8%D8%A7%D9%86%D8%AF%D9%86-%D9%88%DB%8C%D8%AF%DB%8C%D9%88%D9%87%D8%A7-%D8%A8%D8%AF%D9%88%D9%86-%D8%AE%D9%88%D9%86%D8%B1%DB%8C%D8%B2%DB%8C-oixi6slfrcpv</link>
                <description>در این پست می‌خوام یه نرم‌افزار رایگان معرفی کنم که بدون اینکه نیاز باشه تا دوباره رندر بگیرید یا انکود کنید بتونید یک سری کارها مثل بریدن (Trim) یه فایل ویدیویی، اضافه کردن دو تا ویدیو به هم یا حتی تبدیل فرمت‌ها رو انجام بدید. برای اینکار لازم هست که نرم‌افزار Avidemux رو دانلود بکنید.بریدن ویدیوکار با این نرم‌افزار خیلی راحته. برای بریدن یک ویدیو کافیه که نرم‌افزار رو باز بکنید و بعد می‌تونید فایلتون رو در فضای خالی اون Drag&amp;Drop کنید یا مثل خیلی از نرم‌افزار‌ها از بخش File روی گزینه Open کلیک کنید و یا از آیکون پوشه که در بالای نرم‌افزار وجود داره (تنها آیکون فعال وقتی نرم‌افزار رو باز می‌کنید) استفاده کنید.حالا باید بخش‌های ابتدایی و انتهایی فایلتون رو که قراره بریده بشن انتخاب بکنید. برای انتخاب محل شروع بریدن باید ابتدای روی زمان مورد نظر قرار بگیرید. برای اینکار از نوار پایین استفاده کنید. همچنین برای Seek به جلو و عقب می‌تونید از کلید‌های بالا و پایین یا گزینه‌های پایین نوار پخش استفاده کنید. پس از انتخاب محل شروع روی گزینه‌ی Set start marker که به‌صورت حرف A روی یک مستطیل قرمز نشان ‌داده شده است کلیک کنید (قاعدتاً اگر از ابتدای فایل را نیاز دارید تنها کافیست انتهای بریدن رو مشخص کنید). برای مشخص کردن انتهای بریدن هم از گزینه‌ی Set end marker‌که به‌صورت حرف B روی مستطیل سفید مشخص شده است استفاده کنید.برای مرحله آخر یعنی ذخیره‌ی بخش انتخاب شده از ویدیو، کافیه که از کلید‌های ترکیبی Ctrl + S و یا از آیکون Save (فلاپی‌) استفاده کنید. برای مثال، در ادامه فرآیند بریدن یک ویدیو رو نشون دادم.اضافه کردن دو ویدیو به همدیگربرای اینکار تنها کافیه که فایل ویدیوی ابتدایی رو در نرم‌افزار باز کرده و سپس فایل دوم را روی آن Drag&amp;Drop کنید یا از مسیر File گزینه‌ی Append (کلید‌های ترکیبی Ctrl + A) استفاده کنید. بعد به راحتی و سرعت فایلتون رو هر کجا خواستید ذخیره کنید.نکات دیگرنکته ۱:‌ از شکل چرخنده مانند روبروی نوار پخش می‌توانید برای اینکه ۵ ثانیه با سرعت‌های مختلف به جلو و عقب برید، استفاده کنید.نکته ۲: در بخش Output Format می‌توانید فرمت فایل خروجی را انتخاب کنید.نکته ۳: با کلیک روی گزینه‌ی :Time در بخش انتهایی نرم‌افزار می‌تواند زمان را کاملا دقیق برای بریدن انتخاب کنید.نکته ۴:‌ قابلیت‌های دیگر نرم‌افزار رو خودتون کشف کنید. :)این پست، قسمت هشتم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه‌ی این کار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسین ستاریان</author>
                <pubDate>Tue, 28 Jul 2020 22:46:17 +0430</pubDate>
            </item>
                    <item>
                <title>ساخت API برای Archillect با استفاده از Cloudflare Workers</title>
                <link>https://virgool.io/internerds/cloudflare-workers-archillect-api-hn4cbntamacf</link>
                <description>توی این پست با استفاده از Cloudflare Workers که یک سرویس Edge Computing بدون‌سرور (serverless) با جاوا اسکریپت و  APIای مشابه ServiceWorker‌هاست، با استفاده از اسکریپتی که در زمان پاسخ به ریکوئست اجرا می‌شه، دو API Endpoint-طور می‌سازیم و یک دکمه دانلود به صفحه اضافه می‌کنیم.نتیجه نهایی رو می‌تونید در archillect.mhsattarian.workers.dev و کد‌ها رو در ریپازیتوری گیت‌هاب ببینید.معرفیقبل از توضیح پروژه و انجام اون، تو این بخش ‌به‌صورت مختصر به معرفی سرویس‌ها و مفاهیمی که دونستن اون‌ها ‌بد نیست و در درک چگونگی کارکرد پروژه کمک می‌کنه می‌پردازم. اگر با مفاهیم/سرویس‌های بدون‌سرور، Edge Computing و Cloudflare و سرویس ورکر‌ها (service workers) آشنایی دارین می‌تونین این بخش رو رد کنین.‏Archillectپروژه Archillectپروژه Archillect که اسم اون از ترکیب دو کلمه Archive  و Intellect گرفته شده، یک ربات [برنامه] هوش مصنوعی (AI) است که ساخته شده تا نوعی محتوی تصویری رو در شبکه‌های مختلف به اشتراک بذاره. پست‌هایی که انتخاب می‌کنه معمولا از Tumblr هستن و تا الان توی توییتر، تلگرام، اینستاگرام و چند شبکه دیگه منتشر می‌شن. علاوه‌بر ربات توییتر Archillect، ربات دیگری به اسم Archillect Links هم لینک هر عکسی که منتشر می‌شه رو زیر همون عکس رو ریپلای می‌کنه.‏Cloudflareدر ساده‌ترین حالت، ‏Cloudflare یک HTTP Cache هست که در حال حاضر در ۲۰۰ موقعیت در سرتاسر جهان درحال اجراست. اما  Cloudflare سرویس‌های بیشتری از محدود ویژگی‌هایی که استاندارد HTTP برای HTTP Cacheها مشخص می‌کند ارائه می‌دهد، مثل DNS و SSL، مقابله با حملات،‌توزیع بار و موارد دیگه. ‏Cloudflare با ارائه سرویس‌هایی مثل مدیریت DNS رایگان، افزونه‌های شخص‌ثالث برای پروسس ریکوئست‌ها و سرویس‌هایی مانند 1.1.1.1 و Warp امروزه بسیار مورد استفاده و قدرتمنده. ‏Edge Computingبرای آشنایی با مدل اجرای بدون‌سرور (serveless) پیشنهاد می‌کنم قسمت «پردازش ابری (Cloud Computing)» از مقدمه پست «تبدیل توییت به عکس با استفاده از توابع بدون سرور Netlify» رو مطالعه کنین.آمازون AWS به عنوان یکی از بزرگترین سرویس دهنده‌های مدل اجرای بدون‌سرور (serverless) در نقاط مختلفی از دنیا مزارع‌سرورهای (server farm) زیادی، به‌صورت دقیق‌تر ۷۷ مرکز، برای پوشش سرویس‌هاش ایجاد کرده. نقشه پوشش این سرور‌ها:نقشه پوشش جغرافیایی سرورهای Amazon AWSدر نظر بگیرید اگر کاربری در غرب آفریقا درخواستی برای یکی از محتوی/سرویس‌های AWS ارسال کند،‌ پکت‌های شبکه (packets) راه زیادی برای فراهم کردن این محتوی/سرویس طی می‌کنند.سرویس‌دهنده‌های دیگه نیز مثل Cloudflare و Fastly، با وجود اینکه نسبت به آمازون شرکت‌های بسیار کوچک‌تری محسوب می‌شن، به دلیل نیاز به پوشش سرتاسری و بهبود سرویس‌های DNS و CDNاشون زیرساخت‌های سرور بزرگ و زیادی در سرتاسر دنیا دارند. نقشه پوشش سرور‌های این دو کمپانی:نقشه پوشش جغرافیایی سرورهای Cloudflareنقشه پوشش جغرافیایی سرورهای Fastlyبه دلیل نیاز به  یک شبکه جهانی برای ارائه CDN و ملاحظات امنیتی، این کمپانی‌ها سرور‌های بسیار بیشتری در گستره جغرافیایی وسیع‌تری در سراسر جهان‌دارند. در نهایت، تمامی این مراکز ساختمون‌های بزرگی با تعداد زیادی سرور هستند که نتیجه ترکیب اون‌ها یک شبکه عظیمه که امکان اجرا در تقریبا همه‌جا (از نظر فیزیکی) -در لبه (Edge) دریافت و پروسس درخواست‌ها- رو میده. چیزی مشابه Write Once, Run Anywhere از نظر فیزیکی.برخلاف سرویس AWS آمازون که برنامه‌ها در مراکز مشخص با هزینه مشخص اجرا می‌شن؛ این دو کمپانی با همکاری هم امکانی ایجاد کردند که برنامه‌ها یکبار نوشته شده و همزمان در تمامی این مراکز مستقر (deploy) بشن.البته آمازون سرویس مشابه به اسم Lambda Edge داره که امکانات کم و بیش مشابهی رو ارائه میده.همچنین برای اجرای برنامه‌ها، بجای ایجاد زمان اجراهای (runtime) مختلف، اجازه می‌دهند که کدهای web assembly رو در Edge اجرا کنیم.‏Cloudflare Workersاگر با جاوا اسکریپت آشنا باشین، احتمالا با مفهوم workerها و به‌ویژه service workerها آشنا هستین؛ ورکر‌ها در حالت کلی اسکریپت‌هایی هستند که قراره در یک ترد (thread) مجزا اجرا بشن و اجرای برنامه اصلی رو که تنها در یک ترد قابل اجراست مختل نکنن.سرویس ورکر‌ها نوع خاصی از ورکرها هستند که وظایف مخصوصی در قبال Web App کردن وب‌سایت دارن، وظایفی مثل کش کردن (برای استفاده آفلاین)، ارسال ناتیفیکیشن (push message)، همگام‌سازی در پس‌زمینه (background sync) و موارد مثل این. به بیان دیگه سرویس ورکر‌ها یک پراکسی قابل برنامه‌ریزی (programmable network proxy) هستند که اجازه می‌دهند چگونگی مدیریت درخواست‌های (requests) صفحه رو کنترل کنیم. ورکرهای کلودفلر (‏Cloudflare Workers) یک راهکار بدون سرور (serverless) و مشابه سرویس‌ورکر‌ها برای edge computing هستند که برای خیلی‌کارها منجمله مدیریت درخواست‌ها استفاده میشن. برنامه‌های نوشته شده که به لطف web assembly با زبان‌های javaScript، Rust و ++C قابل نوشته‌شدن هستن، در تمامی سرور نود‌های (Fastly + Cloudflare) دپلوی می‌شن. نتیجه تمامی این‌ها قابلیت نوشتن اسکریپت‌هاییست که به‌شدت قدرتمند هستن،‌ واقعا سریع اجرا می‌شن و انعطاف‌پذیری بسیار زیادی به برنامه‌نویس‌ها میدن.استفاده از ورکر‌های Cloudflare با محدودیت‌های بسیار سخاوت‌مندانه ۱۰۰ هزار ریکوئست در روز و محدودیت‌هایی در حجم فایل‌های ذخیره سازی رایگان است.مقدمهبه دلیل علاقه‌ای که به پروژه Archillect و محتوی‌ای که به اشتراک می‌ذاره داشتم، می‌خواستم یک API داشته باشم که با استفاده از اون بتونم از این محتوی توی پروژه‌های مختلف استفاده کنم (مشابه استفاده عکس‌های تصادفی از unsplash) یا اون‌ها رو آرشیو کنم.این پروژه API داره اما متاسفانه عمومی نبوده و تنها برای حمایت‌کننده‌ها از طریق Patreon قابل استفاده است.خوشبختانه عکس‌های Archillect با ID ای به‌ترتیب به‌اشتراک‌گذاری (شماره [index])، منتشر می‌شن و این امکان رو می‌داد تا با دونستن ID آخرین عکس به اشتراک گذاشته شده، ساخت یک index برای یک تصادفی خیلی راحت بشه.با دونستن این مورد، اولین روشی که به‌ذهنم رسید استفاده از RSS Feed و ترکیب اون با سرویس‌هایی مثل Integromat برای بدست آوردن ID آخرین محتوی به‌اشتراک‌گذاشته شده بود. اما Archillect هیچ Feedای ارائه نمی‌داد؛ برای همین سرویس‌هایی مثل rss.app رو تست کردم تا بتونم خودم برای اون یک Feed درست کنم. اما این سرویس‌ هم محدودیت‌های زیادی مثل محدود بودن تعداد feedها،‌ تبلیغات و به‌روز‌رسانی کند فیدها (هر ۲۴ ساعت) داشتن.مدتی روش‌های مختلف دیگه‌ای رو تست کردم تا یاد این ویدئو از Wes Bos افتادم:مشابه پست «تبدیل توییت به عکس با استفاده از توابع بدون سرور Netlify» در این پست هم از راهنمایی‌های این ویدئو کمک گرفته‌شده. https://youtu.be/48NWaLkDcME توی این ویدئو Wes Bos با استفاده از یک Cloudflare worker و اتصالش به دامنه خودش یک پروکسی برای دسترسی مستقیم به یک محتوی (عکس یا GIF) از یک صفحه می‌کنه. تقریبا مشابه کاری که ما قصد داریم بکنیم.آماده سازیدر این پروژه از nodejs استفاده می‌کنیم. اگر اون رو نصب ندارید می‌تونید از سایت اصلی Nodejs و یا با استفاده از مدیر بسته (package manger) سیستم‌عاملتون دانلود و نصب کنید.اگر اطمینان ندارید، ورژن LTS را نصب کنید، همچنین پیشنهاد می‌کنم از یک مدیر نسخه (version manager) برای nodejs مثل nvm یا n استفاده کنید:اگر از لینوکس استفاده می‌کنید و node رو نصب ندارید، انتخاب خوبیه که از اول با نصب یکی از اونها اقدام به نصب node کنید. برای مثال با این دستور زیر n رو نصب کنید: curl -L git.io/n-install | bashپس از نصب با اجزای دستورات زیر تو ترمینال از درستی نصبشون مطمئن بشید:node -vnpm -vهمچنین برای این پروژه لازم است در Cloudflare ثبت‌نام کرده و یک اکانت بسازید: سایت Cloudflareبرای ساختن یک Worker می‌تونید وارد حساب Cloudflare خودتون بشین و روی گزینه ورکر از منوی سمت راست کلیک کنین:ساخت Worker جدیداما برای اینکه بتونیم به‌صورت لوکال پروژه رو تست کنیم و در نهایت به‌صورت اتوماتیک اون رو دپلوی کنیم، همچنین اینکه برای مشاهده نتیجه تغییرات مجبور به اعمال تغییرات روی سرور (دستی یا اتوماتیک) نباشیم و همچنین از محدودیت ۱۰۰هزار ریکوئست در روز خرج نکنیم از ابزاری که Cloudflare معرفی کرده به اسم Wrangler استفاده می‌کنیم.‏wrangler‏wrangler ابزاری تحت خط‌فرمان است که به راحتی با npm  نصب میشه:npm install -g @cloudflare/wranglerبعد از نصب نیاز است تا با وارد کردن دستور زیر احراز هویت انجام بدیم:wrangler configبعد از اجرای این دستور مراحل احراز هویت توضیح داده میشه که به‌صورت خلاصه نیاز هست تا وارد اکانت خودتون بشین و از قسمت توکن‌ها یک توکن ایجاد کنین و اون توکن رو در ترمینال وارد کنید.حالا برای ایجاد پروژه از دستور زیر استفاده می‌کنیم. ایجاد پروژه جدید محدود به استفاده از این روش و قالب پیش‌فرض خود کلودفلر نیست و می‌تونید خودتون پروژه‌ای مشابه رو ایجاد کنید، اما برای سادگی و سرعت از همین دستور استفاده می‌کنیم:wrangler generate my-app
# or
wrangler generate my-app https://github.com/cloudflare/worker-template-routerدر اینجا نامی که به پروژه می‌دهیم my-app است و در دایرکتوری‌ای با همین نام ساخته خواهد شد.بعد از ساخته شدن قالب پروژه، پیامی مشاهده می‌کنیم که نیاز است فیلد‌هایی در فایل wrangler.toml رو تغییر بدیم. برای اینکار وارد دایرکتوری پروژه شده و این فایل رو باز می‌کنیم.وارد اکانت کلودفلر خودتون بشید و مانند تصویر «ساخت Worker جدید» از منوی سمت راست Workers رو انتخاب کنید. در ستون سمت راست داخل کادر می‌تونین account_id خودتون رو پیدا کنید.این مقدار رو کپی‌کرده و داخل فایل wrangler.toml در قسمت account_id قرار بدین. توجه ‌کنید که این مقدار باید به‌صورت string باشد، بنابراین کاراکتر‌های &quot; را حذف نکنید.مستندات و نحوه نصب و آماده‌سازی دقیق‌تر رو می‌تونید از این لینک بخونید.اجرای اولیه برنامهفایل index.js رو باز کنید. این فایل فایل اصلی پروژه است که در ابتدا اجرا می‌شود. مقدار این فایل مشابه زیر است:فایل اصلی پروژه با تغییر مقدار پراپرتی main داخل فایل package.json قابل تنظیم است.addEventListener(&#039;fetch&#039;, event =&gt; {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  return new Response(&#039;Hello worker!&#039;, {
    headers: { &#039;content-type&#039;: &#039;text/plain&#039; },
  })
}همونطور که مشاهده می‌کنید، مشابه service workerهای جاوا اسکریپت عمل‌کرده و با دریافت یک ریکوئست  (که با استفاده از eventListenerای که به اونت fetch متصل کرده متوجه اون می‌شه) و پروسس اون، ریسپانس (جواب [response]) رو ارسال می‌کنه.برای اجرا پروژه کافیه از دستور زیر استفاده کنیم:wrangler previewبا اجرای این دستور یک محیط تست (playground) پروژه در مرورگر باز می‌شود:آدرسی که در آدرس‌بار مشاهده می‌کنید به‌عنوان آدرس این ورکر در نظر گرفته می‌شود.دریافت مستقیم تصاویردر ساده‌ترین حالت در این پروژه، می‌خواهیم سایت archillect بدون تغییر نمایش داده بشه. برای اینکار بدین صورت عمل می‌کنیم که ریکوئست دریافت شده رو گرفته و آدرس اون رو به سایت Archillect تغییر میدیم و ریکوئست جدید رو (که با تابع fetch جاوا اسکریپت ایجاد کردیم) به‌عنوان ریسپانس برمی‌گردونیم.این اسکریپت مشابه یک پروکسی برای Archillect عمل کرده و با مشاهده آدرس این ورکر، انگار سایت Archillect رو باز کردیم:بعد از هربار تغییر کد‌ها از دستور wrangler preview برای مشاهده و اجرای ورکر استفاده کنید.ایجاد پروکسی به سایت Archillectپیش از این گفتم که هر تصویر یک id که نشان‌دهنده index اون هست داره و با اضافه‌کردن این id به انتهای آدرس سایت Archillect می‌تونیم صفحه مربوط به اون عکس رو مشاهده کنیم.الان می‌تونیم با اضافه کردن id در انتخاب آدرس ورکر خودمون (که اینجا از آدرس example.com برای نمایش اون استفاده می‌شه) صفحه تصویر رو ببینیم:حالا می‌خواهیم یک آدرس در اختیار داشته باشیم که با وارد کردن اون و اضافه کردن id‌ تصویر، فایل تصویر رو در اختیار داشته باشیم. برای اینکار نیاز هست تا در هنگام دریافت ریکوئست و قبل از ارسال ریسپانس، یعنی زمانی نتیجه ریکوئست ما (ریکوئست تغییر مسیر داده شده) به Archillect مشخص میشه، اون رو پروسس کنیم.نتیحه این ریکوئست طبیعتا یک فایل HTML ‌است؛ برای پروسس این فایل و بدست آوردن یا تغییر مقدار‌هایی که می‌خوایم می‌تونیم از توابع دستکاری string خود javascript استفاده کنیم و یا از API ای که Cloudflare داخل Workerهاش در اختیارمون می‌ذاره به‌نام HTMLRewriter استفاده کنیم.در این قسمت از روش اول استفاده می‌کنیم، برای اینکه بتونیم فایل عکس‌ها رو در آدرسی مثل آدرس زیر در اختیار داشته باشیم، نیاز داریم تا در‌خواست‌ها به آدرس img/ رو به صفحه عکس (آدرس بدون img/) منتقل کرده و با دریافت نتیجه به‌صورت یک فایل HTML،‌ اون رو برای پیدا کردن آدرس عکس پروسس کنیم و در نهایت به آدرس اصلی عکس ریکوئست زده و نتیجه رو برگردانیم.# &lt;worker-address&gt;/&lt;image_id&gt;/img
e.g. example.com/288580/imgبرای گرفتن آدرس اصلی تصویر، در نتیجه ریکوئست‌مون به Archillect (خط ۲۷)، دنبال متا تگ مربوط به open graph با عبارت og:image می‌گردیم که ساختار زیر رو داره (خط ۳۱) و سپس مقدار content اون رو استخراج می‌کنیم:&lt;meta property=&amp;quotog:image&amp;quot content=&amp;quothttps://66.media.tumblr.com/be97eb9f660e30c01b38b1bbbba1d9e6/tumblr_phi9bhxWnj1vyjf2do1_640.jpg&amp;quot&gt;ساخت endpointای برای دریافت فایل تصویردر نتیجه با اضافه کردن img/ در انتهای آدرس هر تصویر،‌می‌تونیم فایل اون تصویر رو در اختیار داشته باشیم.به سرعت بی‌نظیر اجرای این workerها توجه کنید.اضافه کردن دکمه دانلودحال می‌خواهیم به صفحه تصویر (صفحه تصویر در Archillect) یک دکمه دانلود اضافه کنیم. برای اینکار، مشابه قسمت قبلی نیاز است تا فایل HTML صفحه رو پروسس کنیم این‌بار از روش دوم استفاده می‌کنیم.فرم کلی استفاده از HTMLRewriter به صورت زیر است:new HTMLRewriter()
  .on(&#039;*&#039;, new ElementHandler())
  .onDocument(new DocumentHandler())
  .transform(res)برای استفاده از HTMLRewriter، یک instance جدید از این کلاس درست می‌کنیم و با استفاده از متد on و دادن یک سلکتور (Selector) به فرمت سلکتور‌های CSS و یک کلاس مثل ElementHandler به فرم زیر که باید یک یا چند متد element، coments و text به ترتیب برای هندل کردن المان‌های صفحه، کامنت‌ها و متن‌های صفحه پیاده‌سازی کنه یک متد خودمون برای اعمال تغییرات روی صفحه رو می‌سازیم:class ElementHandler {
   element(element) {
      // An incoming element, such as `div`
      console.log(`Incoming element: ${element.tagName}`)
   }
    comments(comment) {
      // An incoming comment
    }
    text(text) {
      // An incoming piece of text
    }
 }سپس با صدا کردن متد transform و دادن مقدار متن HTML خودمون تغییرات را اعمال می‌کنیم.نتیجه در تصویر زیر قابل مشاهده است.به دکمه دانلود در پایین سمت راست تصویر دقت کنید.اضافه کردن دکمه دانلودساخت endpoint دریافت ID آخرین تصویربرای داشتن endpointای که بتونیم با استفاده از اون ID آخرین عکسی که تا الان منتشر شده رو بگیریم، مشابه قسمت‌های قبل کافیست المان آخرین تصویر را پیدا کرده و شماره ID را از آن استخراج کنیم:دریافت ID آخرین تصویر به‌اشتراک گذاشته شدهمنابعتصویر پس‌زمینه: کاور از editorX و فونت از صابر راستی‌کردارمطالب مربوط به بخش «Edge Computing» از ارائه Steve Klabnik</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Fri, 24 Jul 2020 19:50:22 +0430</pubDate>
            </item>
                    <item>
                <title>چای ۷: اجرای دستورات قبلی در ترمینال</title>
                <link>https://virgool.io/internerds/tea-7-terminal-history-ubiallmxbdri</link>
                <description>برای اینکه دستوراتی که قبلا توی shell اجرا کردیم رو دوباره اجرا کنیم معمولا history رو نگاه می‌کنیم:history | grep &lt;search_term&gt;اما روش‌های راحت‌تری هم برای این‌کار هستن که بررسی می‌کنیم:تمامی این اپراتور‌ها هم در bash و هم در zsh قابل استفاده هستند.اجرای دستور قبلیبرای اجرای آخرین دستوری که وارد کردیم می‌تونیم کلید بالا ⬆️ رو بزنیم تا دستور انتخاب بشه، اما اگر بخوایم از دستور قبلی توی دستور فعلی استفاده کنیم، می‌تونیم از از اپراتور !! استفاده کنیم:هنگام استفاده از کلید بالا ⬆️ اگر وسط نوشتن دستوری باشین، فقط بین دستوراتی که مشابه تا اینجای دستور نوشته شده هستن جستجو می‌کنه؛ برای دیدن دستورات قبلی بدون در نظر گرفتن شباهت از Ctrl+P استفاده کنین.pacman -S edex-ui
sudo !!
sudo pacman -S edex-uiیکی از کاربرد‌های زیاد این روش می‌تونه اضافه کردن sudo به ابتدای دستور قبلی باشه.اجرای دستور قبلی توسط اپراتور !!اجرای دستور nام historyاز اولین اجرای سیستم دستوراتی که توی ترمینال اجرا می‌شن توی history ذخیره می‌شن که با همین دستور هم لیست اون‌ها رو میشه دید. هرکدوم از این دستورات یک index دارن که همینطور نشون دهنده ترتیب اجرای اون‌ها هم هست. با دونستن شماره یک دستور و با کمک عملگر ! می‌شه اون دستور رو دوباره اجرا کرد:# history : 105 ping google.com
!105
ping google.comاجرای دستور nام historyجستجو در دستورهای قبلیجستو با حرف شروعبرای استفاده و اجرا دوباره آخرین دستوری که با حرف مثلا q شروع شده می‌تونیم از اپراتور q! استفاده کنیم:توجه کنید که q جزو اپراتور نبوده و جای اون هرکدوم از حروف رو می‌تونیم بذاریم.!s
serve -s . # last command used starting with &#039;s&#039;جستو با حرف شروع جستجو پویا در تاریخچه دستوراتبرای اینکه آخرین دستوری که یک عبارت داخلش استفاده شده، می‌تونیم با استفاده از ترکیب Ctrl+R، جستجو در دستورات قبل رو فعال کرده و عبارت مورد جستجو رو وارد کنیم:# press Ctrl+R
(zsh)    bck-i-search: _ 
(bash)  (reverse-i-search)`&#039;:برای خارج شدن از این حالت، از Ctrl+G یا Ctrl+Q استفاده کنین.جستجو پویا در تاریخچه دستورات جستجو پویا با استفاده از fzf‏fzf یک ابزار جستجوی فازی تحت خط فرمان هست که به کمک اون می‌تونیم خروجی هر دستوری رو به‌صورت فازی جستجو کنیم. می‌تونید fzf رو از مدیر بسته سیستم‌عاملتون نصب کنید.برای استفاده از fzf برای جستجو در history به‌صورت زیر عمل می‌کنیم:history | fzf +s --tacجستجو پویا با استفاده از fzf استفاده از آرگومان‌های دستور قبلاستفاده از آخرین آرگومان دستور قبلبرای تنها استفاده از آخرین آرگومان دستور قبلی می‌تونیم از اپراتور $! استفاده کنیم:echo arg1 arg2 arg3
cd !$
echo arg3استفاده از آخرین آرگومان دستور قبل استفاده از اولین آرگومان دستور قبلبرای استفاده از اولین آرگومان دستور قبلی می‌تونیم از اپراتور ^! استفاده کنیم:echo arg1 arg2 arg3
cd !^
echo arg1استفاده از اولین آرگومان دستور قبل استفاده از دستور قبلی بدون آرگومانبرای استفاده از دستور قبلی بدون آرگومان‌هاش می‌تونیم از اپراتور #! استفاده کنیم:echo arg1 arg2 arg3
cd !#
echo echoاستفاده از دستور قبلی بدون آرگوماناین پست، قسمت هفتم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه‌ی این کار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Mon, 13 Jul 2020 23:10:03 +0430</pubDate>
            </item>
                    <item>
                <title>تبدیل توییت به عکس با استفاده از توابع بدون سرور Netlify</title>
                <link>https://virgool.io/internerds/tweet2img-euitzv4omwr6</link>
                <description>هدف نهایی این پست یا درواقع چیزی که در انتها خواهیم ساخت، یک سرویس تبدیل توییت به عکسه که احتمالا بتونه اشتراک‌گذاری توییت‌ها رو در شبکه‌های اجتماعی دیگه یا آرشیو کردن اون‌ها رو راحت‌تر کنه. اما، جذاب‌تر و مهم‌تر از نتیجه نهایی، نحوه ساخت این سرویسه که در ادامه به تفصیل توضیح داده خواهد شد.خلاصه (TL;DR)برای ساخت این سرویس از Puppeteer یک مرورگر وب بدون واسط (Headless Browser) برای رندر یک صفحه وب (المان Embed توییتر) و تبدیل اون به عکس استفاده می‌کنیم که داخل یک تابع بدون سرور (Serverless Function) اجرا می‌شه. در عین حال، به هیچ احراز هویت و API Key احتیاج نداریم و هیچ هزینه‌ای هم پرداخت نمی‌کنیم. توی این پروژه تماما از جاوا اسکریپت (Javascript) استفاده می‌کنیم، سمت فرانت (Front-end) که البته خیلی وارد جزئیاتش نمی‌شم از فریم‌ورک Svelte، سمت بک (Back-end) هم از Nodejs برای توسعه یک تابع بدون سرور استفاده می‌کنیم که در نهایت روی Netlify دپلوی (مستقر [deploy]) میشه.در ادامه، ابتدا کمی سرویس و معماری بدون‌سرور رو بررسی می‌کنیم، برنامه رو به‌صورت محلی (local) توسعه می‌دیم و تست می‌کنیم و در انتها روی سرویس Netlify مستقر (deploy) می‌کنیم.شمای کلی پروژهقبل از ادامه و بررسی پروژه، می‌تونید نتیجه نهایی رو در tweet2img و کد‌ها رو در ریپازیتوری گیت‌هاب ببینید.لازم به ذکره قسمت‌هایی از این آموزش از راهنمایی‌های این ویدئو از Wes Bos کمک گرفته شده: https://youtu.be/A0Ww-SU7K5E مقدمهپردازش ابری (Cloud Computing)معماری‌های مختلفی در طول سال‌ها برای توسعه سیستم‌های پردازشیِ ابری معرفی و ارائه شده‌اند که یکی از هدف‌های اون‌ها مثل بخش‌های دیگه محاسبات کامپیوتری، تقسیم و جدا کردن سیستم به بخش‌های مستقل و قابل مدیریت است که در نتیجه اون توسعه‌دهندگان وارد جزئیات کمتری برای استقرار (دپلوی [deploy]) سرویس‌های خودشون بشن. در نتیجه سرویس‌های ابری مختلفی با سطوح انتزاع مختلفی برای استفاده موجود هستند، کاربر می‌تواند پایین‌ترین سطح انتزاع را انتخاب کرده و جزئیات سرور مثل میزان فضای ذخیره‌سازی و مصرف حافظه را کنترل کند و یا تنها در سطح مدیریت‌شده‌تری قرار گرفته و تنها درگیر انتخاب سیستم‌عامل و نصب نرم‌افزار‌های مورد نیاز خود داخل یک ماشین مجازی (Virtual Machine) شود.معماری‌های پردازش ابری و موارد مورد نیاز به رسیدگیتوابع بدون سرور (Serverless Functions)xkcd 927تابع به‌عنوان سرویس ([Function As A Service [FAAS) دسته‌بندی‌ای از سرویس‌های پردازش ابری‌ست که اپلیکیشن‌های ساخته شده توسط این مدل، از معماری بدون سرور استفاده می‌کنند. بدون سرور (Serverless) یک معماری و مدل اجرا (Execution Model) پردازش ابری است که در اون ارائه دهنده سرویس ابری (Cloud Provider) سرور را مدیریت کرده و به‌صورت پویا (dynamically) منابع مورد نیاز سرور را اختصاص میده. بنابراین توسعه دهنده می‌تواند تنها روی توسعه کد خودش تمرکز بکنه و ارائه دهنده سرویس باقی جزئیات را مدیریت می‌کنه.بدون سرور به این معنی نیست که هیچ سروری اجرای کد‌ها رو برعهده نداره -که عملا منطقی نیست- اما به این منظوره که پیچیدگی‌های ایجاد و نگهداری سرورها حذف شده و تنها ماهیت و کد لازم برای اجرای سرویس نیازمند پیاده‌سازی‌ست.از دیگر مزیت‌های این مدل اجرا، کاهش هزینه‌های استفرار و ارائه سرویس‌ها و همچنین استفاده بهینه از منابع سروره، چون که کاربر هزینه‌ای برای زمان‌هایی که سرور بی‌کار (idle) است پرداخت نمی‌کنه.ارائه‌دهنده‌های اصلی سرویس‌های ابریتقریبا تمامی ارائه‌ دهندگان اصلی سرویس‌های ابری سرویس‌های FAAS ارائه می‌دهند؛ در اکثر اون‌ها برای استفاده از این مدل اجرا نیاز است تا اپلیکیشن باندل (bundle) شده و در قالب یک فایل Zip برای اجرا روی سرویس قرار گیرد.در این پروژه از سرویس Netlify برای دپلوی برنامه استفاده می‌کنیم که سرویس تابع بدون سرور اون (Netlify Functions) از سرویس AWS Lambda آمازون استفاده می‌کنه. همچنین، امکاناتی برای تست لوکال (محلی [local]) توابع -بدون سرور- و باندل کردن، دپلوی و ورژن‌بندی اون‌ها در اختیار میذاره که به‌شدت توسعه پروژه رو ساده می‌کنه.صورت کلی یک تابع بدون سرور سرویس Netlify به‌صورت زیره:// functions/foo.js
exports . handler = async ( event , context ) =&gt; {
    return {
        statusCode : 200 , 
        body : “ We are now split 
    }; 
}این تابع هروقت ریکوئست‌ای (درخواست [request]) به آدرس مشخص شده اون (اینجا: img/) ارسال بشه، اجرا می‌شه و در نهایت هر مقداری برگردانده (return) شود به‌عنوان جواب ریکوئست ارسال می‌شه. در پلن رایگان، Netlify نهایتا ۱۰ ثانیه فرصت اجرا به هر تابع می‌دهد. ساخت خودکار تصویرپروژه Ronin از 100r.coبرای ساخت سرویس تبدیل توییت به عکسمون، نیاز داریم تا بتونیم به‌صورت برنامه‌نویسی شده یک تصویر بسازیم؛ برای این کار روش‌های مختلفی وجود داره که بیشتر محدود به زبان انگلیسی (به دلیل عدم پشتیبانی از فونت فارسی)، کُند و یا بدون امکانات شخصی‌سازی هستن. همچنین روش‌هایی نظیر استفاده از Context API با وجود قدرت و سرعت زیاد، به دلیل تفاوت محتوی توییت‌ها، مشخص نبودن طول توییت -نه نهایت طول- و همینطور تصاویر، پیش‌نمایش لینک‌ها و توییت‌های ضمیمه شده آن، مشخص‌نیست و نیاز به محاسبه نسبتا پیچیده داره، رسیدن به نتیجه مطلوب اصلا راحت نیست. یکی از روش‌هایی که مدتی‌ست مرسوم شده و به نسبت بسیار ساده است، استفاده از قدرت بی‌نظیر HTML و CSS برای ساخت المان‌های دیداری و سپس تبدیلش به تصویره؛ استفاده از این روش، قدرت شخصی سازی بی‌نظیری به ما میده و در عین حال سریع و قابل اتکاست.چیدمان تصویر با استفاده از Puppeteerبرای اینکه تصویر را با استفاده از تکنولوژی‌های وب بسازیم، نیاز به ابزاری داریم تا بتونه عملیات رندر (چیدمان [Render]) صفحه وب متشکل از HTML و CSS مورد نظر رو انجام بده و توانایی ارائه خروجی تصویر هم داشته باشه. برای اینکار از یک مرورگر وب بدون واسط (Headless Browser) به نام Puppeteer استفاده می‌کنیم که امروزه بسیار پر استفاده است.مرورگر وب بدون واسط (Headless Browser)یک مرورگر بدون واسطه، یک مرورگر وب بدون رابط گرافیکی و با قابلیت کنترل بالا و خودکار است که امکان پردازش و رندر یک صفحه وب همانند یک مرورگر عادی را در محیطی قابل برنامه‌ریزی و مدیریت شده می‌دهد.دو نمونه از ابزارهای کنترل و کار با این مرورگر‌ها PhantomJS و Puppeteer هستند که هر دو از موتور V8 کرومیوم استفاده می‌کنند. همینطور مرورگر کروم نصب شده روی سیستم نیز می‌تواند در حالت بدون واسط اجرا شود.‏Puppeteer این امکان رو میده تا داخل کد جاوا اسکریپت خودمون یک مرورگر کروم اجرا کرده، صفحه مورد نظر رو داخل اون رندر کرده و از اون یک اسکرین‌شات (Screenshot) ذخیره کنیم.آماده سازیهمون‌طور که بالاتر گفته شد، در این پروژه از nodejs استفاده می‌کنیم. اگر اون رو نصب ندارید می‌تونید از سایت اصلی Nodejs و یا با استفاده از مدیر بسته (package manger) سیستم‌عاملتون دانلود و نصب کنید.اگر اطمینان ندارید، ورژن LTS را نصب کنید، همچنین پیشنهاد می‌کنم از یک مدیر نسخه (version manager) برای nodejs مثل nvm یا n استفاده کنید:اگر از لینوکس استفاده می‌کنید و node رو نصب ندارید، انتخاب خوبیه که از اول با نصب یکی از این دو اقدام به نصبشون بکنید. برای مثال با این دستور زیر n رو نصب کنید:                   curl -L git.io/n-install | bashپس از نصب با اجزای دستورات زیر تو ترمینال از درستی نصبشون مطمئن بشید:node -vnpm -vهمچنین برای این پروژه لازم است در Netlify ثبت‌نام کرده و یک تیم بسازید: سایت Netlifyساخت پروژه و مفاهیم اولیهبرای شروع توی یک دایرکتوری جدید یک پروژه ایجاد کنید. از اونجایی که در این پروژه از فریمورک svelte استفاده می‌کنم،‌ پروژه خودم (با نام tweet2img) رو از template پیش‌فرض خودشون با استفاده از degit که یک ابزار scaffolding هست می‌سازم:npx degit sveltejs/template tweet2imgتوجه کنید که هیچ لزومی به استفاده از svelte نیست و پروژه خودتون رو به‌هر صورتی که تمایل دارید بسازید.با وارد کردن این دستور، پروژه‌ای با ساختار تصویر زیر ساخته می‌شه:ساخت پروژهحالا، وارد دایرکتوری پروژه شده و با استفاده از دستور زیر پکیج‌های مورد نیاز پروژه (dependencies) رو نصب می‌کنیم:npm iهمچنین می‌تونیم با استفاده از دستور npm start پروژه رو اجرا و مشاهده کنیم.آماده‌سازی netlify-cliبرای اینکه ‌بتونیم توابع بدون سرور خودمون رو به‌صورت لوکال تست کنیم و در نهایت مستقیم ‌اون‌ها رو منتشر کنیم، نیاز به ابزاری داریم تا بتونه مشابه محیط اجرای نهایی (پس از انتشار) اون‌ها رو اجرا بکنه. برای اینکار Netlify ابزاری تحت ترمینال به نام netlify-cli دارد. این پکیج رو به‌صورت عمومی (global) روی سیستم نصب می‌کنیم:npm i -g netlify-cliبا اجرای این دستور netlify-cli به‌صورت عمومی روی سیستم نصب می‌شود و از هر دایرکتوری‌ای می‌تونیم اون رو اجرا کنیم. در اولین استفاده لازم است با استفاده از دستور زیر احراز هویت کنیم:netlify loginبا اجرای این دستور اگر در netlify لاگین باشین صفحه‌ای مشابه تصویر زیر باز می‌شود، روی دکمه Authorize کلیک کنید:احراز هویت در netlifyپس احراز هویت، netlify اطلاعات مربوط به کاربر فعلی را در آدرس زیر ذخیره می‌کند:~/.netlify/config.jsonبرای مطالعه بیشتر در مورد احراز هویت و تغییر توکن و موارد دیگه این قسمت از مستندات رو بخونید.اجرای اولیه پروژهحالا می‌توانیم وارد دایرکتوری پروژه شده و با استفاده از دستور زیر پروژه رو به‌صورت لوکال اجرا کنیم:netlify devبا اجرای این دستور، netlify-cli به‌صورت خودکار نوع پروژه و دستور لازم برای اجرای اون رو تشخیص داده و پروژه رو روی پورت 8888: اجرا می‌کنه.لازم به ذکره که netlify پروژه رو با استفاده از دستور npm start روی پورت پیش‌فرض دستور که اینجا 5000: هست اجرا می‌کنه و بعد یک پروکسی به اون پروژه توی پورت 8888: ایجاد می‌کنه تا با اینکار آدرس‌های مربوط به توابع بدون سرور رو مدیریت کنه؛ همینطور بتونه تغییرات فرانت پروژه و تغییرات توابع رو به‌صورت مجزا اجرا و اعمال کنه.حال با مشاهده آدرس localhost:8888 توی مرورگر می‌تونیم نمایی اولیه از پروژه داشته باشیم:اجرای پروژه اولیهتنظیمات Netlifyبرای شخصی‌سازی و تنظیم Netlify از یک فایل TOML استفاده می‌کنیم. برای اینکار در root پروژه یک فایل با نام netlify.toml بسازید:ساخت فایل تنظیمات Netlifyسپس کدهای زیر را داخل فایل کپی کنید. با قرار دادن این کدها، موارد زیر را برای زمان ساخت پروژه (مشخص شده توسط [build]) مشخص می‌کنیم:دایرکتوری اصلی پروژه که لازم است serve بشود دایرکتوری public است.توابع بدون سرور ما در دایرکتوری api قرار خواهند گرفت.برای ساخت پروژه لازم است از دستور npm run build استفاده شود.[build]
  publish = &amp;quotpublic&amp;quot
  functions = &amp;quotapi&amp;quot
  command = &amp;quotnpm run build&amp;quotاگر برخلاف این پروژه از هیچ فرم‌ورکی استفاده نمی‌کردین و نیازی به هیچ دستوری برای ساخت (build) پروژه نبود مقدار اون رو برابر # قرار بدین.ساخت اولین تابع بدون سرورساختار توابع بدون سرور به این صورته که هر دایرکتوری داخل دایرکتوری‌ای که برای توابع بدون سرور تنظیم کردیم (اینجا api/.) یک endpoint به آدرس اسم اون دایرکتوری خواهد ساخت که اسکریپت js با همون اسم رو اجرا می‌کنه.برای مثال با ساختن دایرکتوری و اسکریپت زیر:./api/random/random.jsیک endpoint به آدرس زیر خواهیم داشت که نتیجه اجرای اسکریپت random.js رو با هر ریکوئست پاسخ میده./.netlify/functions/randomمشابه توضیح بالا دایرکتوری و فایل random رو در  root پروژه می‌سازیم:ساخت api با نام randomهدف این تابع این است تا با هر ریکوئست یک عدد تصادفی (random) به عنوان ریسپانس برگرداند. این تابع رو به‌صورت زیر می‌نویسیم:// api/random/random.js
exports.handler = async (event, context) =&gt; {
    return {
        statusCode: 200,
        body: Math.random().toString(),
    };
};
حال می‌توانیم با وارد کردن آدرس زیر در مرورگر نتیجه اجرای این دستور رو مشاهده کنیم:http://localhost:8888/.netlify/functions/randomایجاد اعداد تصادفی با استفاده از تابع بدون سرور randomدریافت پارامتر‌ها و متد درخواستبه ورودی‌های تابعی که در کد خودمون export کردیم دقت کنید. این ورودی‌ها اطلاعات لازم درباره درخواست ارسال شده و محیط اجرای تابع رو در اختیار ما می‌ذارن. شکل کلی اون‌ها به‌صورت زیره:exports.handler = async (event, context, callback) =&gt; {}پارامتر callback برای ارسال response استفاده می‌شده که ما در مثال قبل تنها با return کرد یک object اینکار رو انجام دادیم. بجای return کردن میشه از تابع callback به‌صورت زیر استفاده کرد:exports.handler = function(event, context, callback) {
    callback(null, { // null indicates no error
        statusCode: 200,
        body: &amp;quotHello, World&amp;quot
    });
}ورودی event، اطلاعات زیر رو در اختیار ما می‌ذاره:// whats inside event parameter:

{
    &amp;quotpath&amp;quot: &amp;quotPath parameter&amp;quot,
    &amp;quothttpMethod&amp;quot: &amp;quotIncoming request&#039;s method name&amp;quot
    &amp;quotheaders&amp;quot: {Incoming request headers}
    &amp;quotqueryStringParameters&amp;quot: {query string parameters }
    &amp;quotbody&amp;quot: &amp;quotA JSON string of the request payload.&amp;quot
    &amp;quotisBase64Encoded&amp;quot: &amp;quotA boolean flag to indicate if the applicable request payload is Base64-encode&amp;quot
}بنابراین با استفاده از event.httpMethod می‌تونیم نوع درخواست ارسال شده رو کنترل کنیم و برای مثال تنها به‌ درخواست‌های POST پاسخ بدیم و با استفاده از event.queryStringParameters می‌تونیم پارامتر‌های ارسال شده توی URL رو به‌صورت یک Object در اختیار داشته باشیم.برای نمونه اسکریپت greet رو در آدرس زیر می‌سازیم:./api/greet/greet.jsو کد زیر رو توی اون قرار بدید:exports.handler = async (event, context) =&gt; {
    const { name } = event.queryStringParameters;
    return {
        statusCode: 200,
        body: `Hello, ${name || &amp;quotworld&amp;quot}!`,
    };
};تغییرات داخل فایل توابع به‌صورت آنی بعد از ذخیره شدن فایل، اعمال می‌شن اما با ساخت تابع جدید نیاز به اجرای دوباره دستور netlify dev است. بنابراین دستور را دوباره اجرا کنید تا endpoint این تابع ساخته شود.حال با وارد کردن آدرس زیر و قرار دادن یک اسم در انتها می‌تونید پیامی حاوی اون اسم رو برگردونید:http://localhost:8888/.netlify/functions/greet?name=اگر اسمی فرستاده نشود بجای آن world قرار می‌‌گیرد.اجرای تابع greetتغییر آدرس توابعاجرای توابع با همچین آدرس‌هایی نه قشنگه و نه راحت. برای همین لازم داریم درخواست‌ها رو از یک آدرس ساده‌تر redirect کنیم به این آدرس. برای مثال مشخص کنیم که هر ریکوئست که به random/ رسید اون رو به netlify/functions/random./ پاس بده:/random  --&gt;    /.netlify/functions/randomبرای اینکار Netlify با استفاده از یک فایل اجازه مشخص کردن ریدایرکت‌ها رو به ما میده:داخل دایرکتوری public یک فایل به نام redirects_ می‌سازیم و داخل اون در هر سطر مشخص می‌کنیم با دریافت ریکوئست به هر آدرس، به کدام آدرس و با کدام status code ریدایرکت شویم:این موارد رو با space از هم جدا کرده و در هر سطر یک مورد را وارد می‌کنیم./random /.netlify/functions/random 200
/greet /.netlify/functions/greet 200حال با وارد کردن آدرس‌های زیر می‌تونیم توابع رو اجرا کنیم:http://localhost:8888/randomhttp://localhost:8888/greetنصب پکیج و استفاده در تابع بدون سرورهمانطور که در مقدمه پست اشاره شد، سرویس‌های ارائه دهنده سرویس FAAs،‌ توابع بدون سرور رو به‌صورت یک فایل bundle شده به فرمت zip دریافت و اجرا می‌کنند. در اینجا عملیات باندل کردن و آماده سازی توابع رو netlify-cli با استفاده از webpack به‌صورت خودکار انجام میده. به‌صورت دقیق‌تر، از ورژن ۲.۷ عملیات باندل کردن به‌صورت خودکار انجام می‌شه و قبل از اون باید از ابزارهایی مثل netlify-lambda استفاده می‌شد.در اینجا هم اگر می‌خواهید از import بجای require استفاده کنید نیاز است تا با استفاده از netlify-lambda و تنظیم اون تابع رو build کنید.بنابراین می‌تونیم بدون اعمال تنظیمات خاصی از پکیج‌های شخص‌ثالث (third-part packages) در پروژه خودمون استفاده کنیم.برای تست این مورد یک تابع جدید با نام quote در آدرس زیر بسازید:./api/quote/quote.jsو ترمینال را در این آدرس باز کرده و با استفاده از دستور زیر یک پکیج Initialize کنید:npm init -yبا اجرای این دستور فایل package.json در دایکتوری تابع ساخته شده و می‌تونیم پکیج‌هایی که لازم داریم رو نصب کنیم. در این تابع می‌خوام از جملات master Yoda استفاده کنم. برای همین پکیج yodaquotes رو نصب می‌کنم:npm i yodaquotesبعد از نصب این پکیج، می‌تونم از اون توی تابع خودم استفاده کنم:const yodaQuotes = require(&amp;quotyodaquotes&amp;quot);

exports.handler = async (event, context) =&gt; ({
    statusCode: 200,
    body: yodaQuotes(),
});مجددا بعد از ساخت این تابع دستور netlify dev رو ری‌استارت کنید و مقادیر لازم برای ری‌دایرکت کردن تابع رو در فایل redirects_ قرار بدین.الان با وارد کردن آدرس زیر می‌تونیم از دستورات یودا بهره‌مند بشیم:دریافت یک quote از Yodaبالاخرهتبدیل توییت به عکس با استفاده از puppeteerتوابعی که در قسمت‌های قبل درست کردیم صرفا جنبه آموزشی داشتن تا ببینیم چطوری توابع بدون سرور بسازیم و از اون‌ها استفاده کنیم. اما بالاخره رسیدیم به هدف اصلی این پست، که تبدیل توییت به عکسه.همونطور که قبلا اشاره شد برای تبدیل توییت به عکس از puppeteer استفاده می‌کنیم. برای این کار المان embed یک توییت رو با استفاده از Oembed API توییتر دریافت می‌کنیم.اگر سعی کرده باشید از twitter یک API key بگیرید احتمالا می‌دونید که پروسه راحت و سریعی نیست و چندین مرحله پرسش و پاسخ رو طی می‌کنید که ممکنه تا چند روز طول می‌کشه. اما ما اینجا از Oembed API استفاده می‌کنیم که یک API عمومی و رایگان هست.این API به این صورت عمل می‌کنه که با دریافت آدرس یک توییت، اطلاعات لازم برای embed کردن توییت شامل یک کد HTML مربوط به اون رو ارائه میده:نتیجه Oembed API توییتراگر این کد HTML خروجی‌ای مشابه تصویر زیر رندر می‌کنه:المان embed یک توییت از Fermat&#039;s Libraryما از این المان استفاده کرده و با استفاده از puppeteer از اون یک اسکرین‌شات می‌گیریم.ایجاد و راه‌اندازی پروژهبرای شروع مشابه آخرین مثال قسمت قبل، یک تابع جدید (مثلا img) می‌سازیم و یک پکیج initialize می‌کنیم و پکیج‌های لازم رو نصب می‌کنیم که در ادامه بررسی می‌شن:cd api/img
npm init -y
npm i chrome-aws-lambda puppeteer-core node-fetch waaitدر اینجا دلیل اینکه چرا خود puppeteer رو نصب نکرده و puppeteer-core رو نصب کردیم به این خاطره که با نصب puppeteer، همراه خودش یک مرورگر کروم رو هم نصب می‌کنه که ما احتیاجی نداریم. به عنوان مرورگر ما از chrome-aws-lambda استفاده می‌کنیم که یک نسخه باینری از مرورگر کروم است که برای اجرا در محیط‌های aws lambda آمازون و cloud functions گوگل بهینه و آماده شده.همونطور که قبلا اشاره شد، Netlify از سرویس‌های aws آمازون استفاده می‌کنه.پکیج‌های node-fetch و waait پکیج‌های دلخواهی هستند که احتیاجی بهشون نداریم اما برای راحتی کار ازشون استفاده کردم. می‌تونید این پکیج‌هارو نصب نکرده یا از پکیج‌های مشابهشون استفاده کنید.کد اولیه اسکرین‌شاتبرای اسکرین‌شات گرفتن، از کد زیر از Leigh Halliday استفاده کردم که نحوه استفاده از کروم رو در اجرای لوکال و هنگام اجرا روی سرور تفکیک کرده: https://gist.github.com/mhsattarian/c420dddc9390d641ed962ce4ec2d7c36 در این کد توی تابع getOptions با پارامتر isDev مشخص می‌شود که درحال اجرای کد در لوکال هستیم و یا روی سرور که بر اساس اون مروگر کروم نصب شده روی سیستم (در حالت بدون واسطه [headless] و مخفی [incognito]) و یا chrome-aws-lambda به‌عنوان مرورگر مورد استفاده انتخاب می‌شود.تابع getScreenshot هم وظیفه اجرای مرورگر (تابع launch)، باز کردن صفحه به آدرس مورد نظر (تابع goto و پارامتر url) و اسکرین شات گرفتن از آن (تابع screenshot) را بر عهده دارد. همینطور، با استفاده از تابع setViewPort مشخص می‌کنیم که document در هنگام لود صفحه چه اندازه‌ای باشه و از آرگومان deviceScaleFactor برای این استفاده کردیم که اندازه document بزرگتر باشه و تصاویر با کیفیت‌تری در هنگام اسکرین‌شات گرفتن خروجی بگیریم.اعمال تغییرات۱. از اونجایی که ما می‌خواهیم المان Embed توییت به‌صورت HTML رو استفاده کنیم و همچنین نه از کل صفحه که از یک المان خاص احتیاج‌داریم اسکرین‌شات گرفته بشه، کد رو به‌صورت زیر تغییر میدیم: https://gist.github.com/mhsattarian/8f380c851b2eaaae11b299f330f66670 در اینجا بجای استفاده از متد page.goto از تکه کد زیر برای رندر یک تکه کد HTML استفاده کردیم:بالاتر توضیح داده‌شد که این تکه HTML قرار است از سرویس Oembed توییتر دریافت شود.page.setContent(html, 
    { waitUntil: [&amp;quotnetworkidle0&amp;quot, &amp;quotdomcontentloaded&amp;quot], }
);که در این کد مشخص کردیم مقدار متغیر html رو رندر کرده و تا هنگام لود تمامی المان‌ها صبر کن.۲. تغییر دیگر، استفاده از متد page.evaluate برای اعمال یک اسکریپت جاوا اسکریپت درون صفحه رندر شده است. با استفاده از این تابع می‌توانیم یک اسکریپت دلخواه را درون صفحه اجرا کرده و خروجی‌ای از آن دریافت کنیم. در اینجا از این تابع برای محاسبه مختصات باکس المان embed با کمک متد getBoundingClientRect استفاده کردیم تا بعدا از اون برای مشخص کردن محدوده مورد نظر برای اسکرین‌شات گرفتن استفاده کنیم. نکته جانبیتوییتر پیش از این از web components در المان خود استفاده می‌کرد و المان‌هایی که نیاز به استایل‌دهی آن‌ها داشتیم، در shadow root قرار می‌گرفتند. استایل دهی به این المان‌ها از طریق css به راحتی ممکن نبود و به همین دلیل می‌بایست که از متد element.shadowRoot برای دریافت المان‌های صفحه استفاده می‌کردیم.اما حدود یک ماه پیش با تغییر المان embed خودشون و استفاده از iframe تا حدودی این کار -در روش استفاده ما- راحت‌تر شده.ساخت تابع بدون سرور و نحوه استفاده الان که نحوه اسکرین‌شات رو بررسی کردیم می‌تونیم تابع بدون سرور خودمون رو بنویسیم. برای اینکار فایل اسکریپتی که نوشتیم (api/img/img.js/.) رو باز می‌کنیم و محتوی کد بالا و سپس کد زیر رو وارد می‌کنیم: https://gist.github.com/mhsattarian/447f6d0105e6652f344a01879e16e083  آدرس توییت مورد نظر رو از پارامتر url دریافت کرده (خط ۶) و با استفاده از Oembed API توییتر کد HTML المان رو دریافت می‌کنیم (خط ۸).سپس مقدار Environment Variable ای با نام CHROME رو می‌خونیم تا با استفاده از اون مشخص کنیم آیا در اجرای محلی هستیم یا اجرای روی سرور (خط ۱۳).برای اینکه این مقدار در اجراهای لوکال مشخص شود، در فایل package.json به صورت زیر اسکریپتی برای اجرای پروژه می‌نویسیم:نوشتن اسکریپت برای شروع پروژههمینطور پکیج cross-env رو هم به‌صورت زیر نصب می‌کنیم:npm i cross-envبا استفاده از تابع getScreenshot ای که نوشتیم نتیجه اسکرین‌شات رو به‌صورت بافر (Buffer) دریافت می‌کنیم (خط ۱۴).در نهایت مثل قبل یک Object را return می‌کنیم که به عنوان body بافر عکس که تبدیل به Base64 شده را قرار میدیم. همینطور با پراپرتی isBase64Encoded مشخص می‌کنیم که مقدار body یک فایل به فرمت base64 است (خط ۱۶).نتیجه اجرای تمامی این مراحل، تابعی است که با دریافت آدرس یک توییت در پارامتر url اش می‌تونه اون رو تبدیل به تصویر کرده و خروجی رو برگردونه. برای مثال آدرس یک توییت رو در انتهای آدرس زیر قرار بدین:http://localhost:8888/img?url=نتیجه تبدیل توییت به عکسدر انتها، برای انتشار و استقرار سایتتون می‌تونید از دستور زیر استفاده کنید:netlify deploy --prodبا استفاده از این دستور، پروژه شما build شده و با نامی که انتخاب کردید منتشر خواهد شد.خلاصهتولید عکس با استفاده از تکنولوژی‌های وب انعطاف‌پذیری زیادی به ما میده در عین‌حال به‌شدت راحت و سریعه. پروژه‌های زیادی از همین روش در دنیای وب برای تولید تصویر، thumbnail و داده‌های مشابه استفاده می‌کنند. همینطور سرویس‌هایی مانند HCTI هستند که API برای اتوماتیک کردن همین پروسه در اختیار می‌گذارن. توابع بدون سرور هم امکان پیاده‌سازی سرویس‌های سمت بک رو -بیشتر مواقع- در راحت‌ترین شرایط فراهم می‌کنن که سرویس‌های بسیاری بجز Netlify برای استفاده رایگان از این مدل اجرا مثل Vercel و Begin وجود دارن.امیدوارم جالب بوده باشه براتون.دیگر منابعتصویر پس‌زمینه:  کاور از editorX و فونت از صابر راستی‌کردارنمودار ابتدای پست، ساخته شده به کمک cloudcraft.coمقایسه معماری‌های پردازش ابری، ساخته شده به کمک excalidrawتصویر سازی بخش «توابع بدون سرور»، از xkcdنمودار ارائه‌دهندگان سرویس‌های ابری از وبلاگ maxkelsenتصویر بخش «ساخت خودکار تصاویر» از پروژه Ronin از 100r.coتصویر بخش «چیدمان تصویر با استفاده از Puppeteer» از buddy.worksپاراگراف اول توضیح «مرورگر وب بدون واسط» از ویکی‌پدیاتوییت نمایش داده‌شده در ابتدای بخش «بالاخره، تبدیل توییت به عکس...» از Fermats Libraryتوییت تبدیل شده به عکس در تصویر انتهایی از Sam Altman</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Thu, 09 Jul 2020 22:29:22 +0430</pubDate>
            </item>
                    <item>
                <title>چای ۶: پنهان‌کردن عمدی فایل‌ها در لینوکس</title>
                <link>https://virgool.io/internerds/tea-6-linux-hide-file-directory-ebwrtwome0ru</link>
                <description>همونطور که می‌دانیم، در فایل سیستم لینوکس، فایل‌هایی که با . (نقطه [Dot]) شروع می‌شوند، پنهان یا به اصطلاح hidden هستند؛ بدین معنی که با مشاهده دایرکتوری (فولدر) شامل این فایل‌ها توسط برنامه‌های مدیریت فایل (File managers) و یا استفاده از دستوراتی مانند ls، آن‌ها نمایش داده و یا پروسس نمی‌شوند.هرچند طبیعتا با فعال کردن نمایش فایل‌های پنهان در برنامه‌های مدیریت فایل توسط Ctrl+H و یا استفاده از دستور ls توسط فلگ ‎-a، این فایل‌ها قابل مشاهده می‌شوند.برای آنکه فایل‌ها و حتی دایرکتوری‌هایی که امکان تغییرنام آن‌ها (اضافه کردن . ابتدای نام) وجود ندارد را پنهان کنیم، می‌توانیم در کنار آن فایل/دایرکتوری یک فایل با نام «‎.hidden» ایجاد کرده و اسم فایل/دایکتوری‌ها را داخل آن به‌صورت یک عنوان در هر سطر می‌نویسیم:پنهان کردن دایرکتوری n فرمت فایل ‎.hidden توسط برنامه‌های پیش‌فرض مدیریت فایل دسکتاپ‌های Gnome ،KDE و Cinnamon یعنی Nautilus و Dolphin و Nemo پشتیبانی می‌شود.منبعاین پست، قسمت ششم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه‌ی این کار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Tue, 16 Jun 2020 23:21:46 +0430</pubDate>
            </item>
                    <item>
                <title>چای ۵: اسکریپت نویسی Shell، بازه‌ها در حلقه for</title>
                <link>https://virgool.io/internerds/tea-5-shell-range-wnicbipm7yft</link>
                <description>به عنوان آدمی که ذره‌ای علاقه به طراحی و گرافیک داره، هیچوقت مخالف رابط‌های گرافیکی (GUI) نبوده و نیستم، اما انجام خیلی از کارها با استفاده از CLI به دلیل قابل برنامه‌نویسی بودن، به میزان بسیار زیادی راحت‌تر و سریع‌تره به‌خصوص کارهایی که قاعده‌مند و قابل تکرار هستند، مثل استفاده از GIT، ایجاد دایکتوری‌های تو‌درتو، تبدیل فایل‌ها و تحت تاثیر قرار دادن افراد!در این قسمت از چای، خیلی کوتاه با استفاده از چند مثال، با عملگر بازه (range operator) در اسکریپت نویسی shell آشنا می‌شیم.حلقه forدر حالت عادی نوشتن یک حلقه for در shell script به‌صورت زیر است:#!/bin/bash
# Basic for loop

for (( c=1; c&lt;=5; c++ ))
do  
   echo $c
doneکه می‌توان آن را در یک خط به‌صورت زیر نوشت:❯ for ((c=1;c&lt;=5;c++)); do echo $c; doneبا اجرای این حلقه اعداد ۱ تا ۵ به‌صورت زیر چاپ می‌شوند:1 
2 
3 
4 
5حلقه forعملگر بازه (range)عملگر بازه‌ها نوشتن حلقه‌های for را ساده‌تر کرده و حتی این اجازه را می‌دهند که بدون نوشتن حلقه for، دستورات را تکرار کرده و نوشتن برنامه‌های تک-خطی (One-liner program) رو بسیار ساده‌تر می‌کنه. فرمت و نحوه استفاده بازه‌ها به‌صورت زیر است:# range operator (pseudo code)
{start..end..step}به مثال‌های زیر توجه کنید:چاپ اعداد بین ۱ تا ۱۰# print numbers from 1 to 10
❯ for i in {1..10}; do echo $i; done
1 
2 
3 
4 
5 
6 
7 
8 
9 
10چاپ اعداد فرد بین ۱ تا ۱۰# print odd numbers from 1 to 10
❯ for i in {1..10..2}; do echo $i; done
1 
3 
5 
7 
9استفاده از بازه‌ها بدون حلقه forهمانطور که گفته شد، از عملگر بازه‌ها می‌توان خارج از حلقه for نیز استفاده کرد؛ اینکار انعطاف‌پذیری زیادی به دستورات میده و اجازه میده بدون نوشتن حلقه for دستورات را تکرار کنیم. به مثال زیر دقت کنین:چاپ اعداد بین ۱ تا ۱۰۰❯ echo {1..100} 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100ساختن دایرکتوری‌هایی با حروف الفبا❯ mkdir {a..z}ساختن دایرکتوری‌هایی با حروف الفبا  تبدیل تصاویر با نام‌های ترکیبی حروف و اعداد ❯ convert {a..b}{1..2}.png output%0d.jpgدر این مثال با استفاده از imagemagick تصاویر زیر رو از png به jpg تبدیل می‌کنیم:تبدیل تصاویر a1، a2، b1 و b2 از png به jpg با استفاده از imagemagickبا کنارهم گذاشتن چند بازه (range) می‌توان تمام جایگشت‌های ترکیب آن‌ها را تولید کرد.در مثال فوق: a1, a2, b1, b2برای آشنایی بیشتر و بهتر با اسکریپت‌نویسی shell این آموزش رو مطالعه کنید.این پست، قسمت پنجم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه‌ی این کار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Sat, 23 May 2020 19:03:25 +0430</pubDate>
            </item>
                    <item>
                <title>چای ۴: خودکارسازی تلگرام، دانلود مدیا‌های یک کانال/گروه</title>
                <link>https://virgool.io/internerds/tea-4-telegram-python-hrfvujw0uemv</link>
                <description>تلگرام به دلیل APIهای فراوانی که ارائه میده، علاوه‌بر اینکه پلتفرم بسیار پویا و خوبیه، قابلیت خودکارسازی بسیار خوبی هم داره. به عنوان نمونه یکی از این خودکار‌سازی‌ها شرایطی را در نظر بگیرین که به هر دلیل نیاز داریم فایل‌های به اشتراک گذاشته شده در یک گروه یا کانال تلگرام را به‌‌صورت دسته‌ای دانلود کنیم، برای مثال، می‌خواهیم ۱۰ فایل آخر، یا فایل‌هایی که پسوند xd. دارند و یا تمامی تصاویر را دانلود کنیم. طبیعتا انجام این‌کار به‌صورت خودکار و برنامه‌نویسی شده بسیار راحت‌تر است. بنابراین در این آموزش با استفاده از پایتون و کتابخونه Telethon تمامی آهنگ‌هایی که در کانال cctracks@ به اشتراک گذاشته شده رو دانلود می‌کنیم.نکتهآهنگ‌هایی که در کانال cctracks@ به اشتراک گذاشته‌شده اند گواهی‌نامه Creative Commons داشته و اشتراک‌گذاری آن‌ها مجاز است.صادقانه خواهش می‌کنم از این روش برای دانلود محتوی دارای حق کپی‌رایت (آهنگ، کتاب و ...) استفاده نکنید. این پست جنبه آموزشی داشته و هدف آن نقض قوانین کپی‌رایت نیست.روشی که در این آموزش استفاده می‌کنیم با توسعه ربات‌های تلگرام متفاوت است، در این روش ما به یک برنامه اجازه می‌دهیم به پلتفرم تلگرام با استفاده از اکانت ما دسترسی داشته باشد. البته کتابخونه Telethon امکان دسترسی به تلگرام به عنوان یک ‌ربات را هم می‌دهد. اما ربات‌های تلگرام قادر به اینکار نیستند و به محتوی گروه‌ها و کانال‌هایی که در آن عضو نیستند دسترسی ندارند.پیش‌نیاز‌هاپایتون ۳+مدیر بسته pipپکیج‌های Telethon و tqdmهمانطور که گفته‌شد برای اینکار نیاز داریم تا یک برنامه با استفاده از اکانت ما به پلتفرم تلگرام وصل شود، برای اینکار نیاز است این برنامه به‌صورتی احراز هویت شود.دریافت اعتبار‌نامه‌هابرای احراز هویت ربات لازم است دو رشته کد api_id و api_hash را از تلگرام دریافت کنیم. برای اینکار وارد  my.telegram.org و سپس قسمت API development tools می‌شویم:صفحه API development toolsدر این صفحه اطلاعات مربوط به برنامه، نظیر نام و توضیحات و نوع آن را به دلخواه خود مشخص کرده و با کلیک بر روی Create application کد‌های  api_id و api_hash را دریافت کنید.این کد‌ها منحصرا برای شما بوده و نباید به اشتراک گذاشته شوند، حتما توجه کنید که آن‌ها را در دسترسی عموم قرار ندین.با استفاده از این کد‌ها برنامه می‌تواند اقدام به احراز هویت کرده و به اکانت ما دسترسی داشته باشد. خوشبختانه کتابخانه Telethon عمل احراز هویت را بسیار ساده کرده که در ادامه بررسی می‌کنیم.دسترسی به پیام‌های یک کانال/گروه تلگرامپس از دریافت اعتبارنامه‌های لازم (api_id و api_hash) می‌توانیم با استفاده از اون‌ها امکان دسترسی به اکانت خودمون و در نتیجه دسترسی به محتوی کانال/گروه‌هایی که در آن‌ها عضو هستیم را به یک برنامه رابط بدهیم. برای اینکار از پایتون و کتابخونه Telethon استفاده می‌کنیم. Telethon امکان استفاده از API تلگرام را بسیار ساده کرده و می‌توان از آن برای کنترل ربات‌ها و اکانت شخصی استفاده کرد، در واقع با استفاده از آن می‌توان هم به عنوان بات و هم به عنوان یک اکانت حقیقی به تلگرام دسترسی داشت.کتابخونه Telethon به راحتی با pip نصب می‌شود:نکته بهتر است قبل از نصب آن‌ها یک محیط مجازی برای این پروژه بسازیم و بعد اقدام به نصب کنیم. (اختیاری)pip install telethonاحراز هویتدر اولین استفاده نیاز داریم تا اقدام به احراز هویت بکنیم. برای اینکار بدین صورت عمل می‌کنیم:from telethon import TelegramClient, events, sync

# These example values won&#039;t work. You must get your own api_id and
# api_hash from https://my.telegram.org, under API Development.
api_id = 12345
api_hash = &#039;0123456789abcdef0123456789abcdef&#039;

client = TelegramClient(&#039;session_name&#039;, api_id, api_hash)
client.start()‌با اجرای این کد،‌ از شما خواسته می‌شود یک bot token و یا یک شماره موبایل برای ورود وارد کنید. از اونجایی که ما نیاز به دسترسی به گروه‌ها و کانال‌های خودمون رو داریم شماره خودمون رو وارد می‌کنیم. با وارد کردن شماره موبایل به صورت 989123456789+  پیامی در تلگرام حاوی کد تایید هویت ارسال می‌شود. این کد را وارد می‌کنیم. در ادامه اگر برای اکانتمون cloud password برای Two-step verification تنظیم کرده باشیم، ‌نیاز است تا آن را هم وارد کنیم:احراز هویتدر نهایت یک فایل به نام session_name.session در کنار برنامه ما ذخیره می‌شود که از آن برای احراز هویت استفاده می‌کنیم.توجه کنید که می‌توانیم sessionهای مختلف با هویت‌های مختلف با اعتبارنامه‌هایی که داریم (api_id و api_hash) داشته باشیم.از این به بعد با استفاده از این فایل احراز هویت را انجام داده و دیگر نیاز به مراحل بالا نیست،‌ مگر برای ورود به یک اکانت دیگر.حالا، برای شروع  یک پیام به خودمون (saved messages) می‌فرستیم:from telethon.sync import TelegramClient, events

api_id = &lt;YOUR APP ID&gt;
api_hash = &amp;quot&lt;YOUR API HASH&gt;&amp;quot

with TelegramClient(&#039;session_name&#039;, api_id, api_hash) as client:
    client.send_message(&#039;me&#039;, &#039;Hello, myself!&#039;)نتیجه رو می‌تونید تو GIF زیر ببینین:ارسال پیام به خودنکتههمونطور که می‌بینین میشه از TelegramClient به عنوان یک context manager استفاده کرد. همچنین، می‌توانیم به لیست تمامی گروه‌ها و کانال‌هایی که در آن‌ها عضو هستیم به‌صورت زیر دسترسی داشته باشیم:from telethon.sync import TelegramClient, events

api_id = &lt;YOUR APP ID&gt;
api_hash = &amp;quot&lt;YOUR API HASH&gt;&amp;quot

with TelegramClient(&#039;session_name&#039;, api_id, api_hash) as client:
    for dialog in client.iter_dialogs():
        print(dialog.name, &#039;has ID&#039;, dialog.id)دانلود مدیا‌های یک کانال/گروهحال که کمی با Telethon آشنا شدیم،‌ می‌تونیم مدیا‌های  کانال cctracks@ رو دانلود کنیم. اگر در این کانال عضو نیستید عضو شوید و کد زیر را اجرا کنید:from telethon.sync import TelegramClient, events
from tqdm import  tqdm
import os

api_id = &lt;YOUR APP ID&gt;
api_hash = &amp;quot&lt;YOUR API HASH&gt;&amp;quot

with TelegramClient(&#039;session_name&#039;, api_id, api_hash) as client:
    messages = client.get_messages(&#039;cctracks&#039;, limit=50)
    print(len(messages))
    for msg in tqdm(messages):
        msg_file = msg.file
        if msg_file and msg_file.mime_type == &#039;audio/mpeg&#039;:
            msg.download_media(file=os.path.join(&#039;musics&#039;, msg_file.name))ابتدا با استفاده از متد get_messages و مشخص کردن limit=50، تا ۵۰ پیام آخر کانال را دریافت کردیم. اگر با استفاده از limit تعداد پیام‌ها مشخص نشوند، تنها یک پیام خوانده می‌شود.سپس با استفاده از متد download_media که هر آبجکت پیام (اینجا  msg) دارد می‌توانیم به راحتی آن را دانلود  کنیم.فایل‌های دانلود شدهاین پست، قسمت چهارم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه اینکار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Wed, 20 May 2020 16:33:05 +0430</pubDate>
            </item>
                    <item>
                <title>چای ۳: چطوری کلاس‌های مجازی دانشگاه رو ضبط کنم؟</title>
                <link>https://virgool.io/internerds/tea-3-lms-screen-recording-ntlo7grxdhva</link>
                <description>خب همونطور که احتمالا میدونید چند ماهی هست که کلاسای دانشگاه‌ها به‌خاطر شیوع بیماری کووید-۱۹ به‌صورت مجازی دارن برگزار می‌شن. به دلایل مختلفی مثلاً اینکه سرعت درس دادن برخی استاد‌ها گاهی کنده و شدیداً نیاز به این داشتم که سرعت پخش ویدیوها رو زیاد کنم و یا بتونم خیلی راحت Seek forward‌ کنم، نیاز داشتم که کلاس‌ها رو به‌صورت ویدیو داشته باشم. مشکل اصلی این بود که کلاس‌ها فقط از طریق سایت دانشگاه قابل دسترسی هستن و خب این باعث میشه در ساعاتی که کلاس‌های عادی در حال پخش هست سرعت سیستم پایین باشه و بعد نکته دیگه این بود که فایل‌های رکورد شده‌ای که روی سایت قرار داره در حقیقت ویدیو نیست و نمی‌تونه اون نیازهایی که من داشتم رو برطرف کنه. لازم به ذکره، دانشگاه ما از ادوبی کانکت برای کلاس‌های مجازیش استفاده می‌کنه.برای ضبط کلاس‌های قرار داده شده روی سایت باید از برنامه‌های رکورد اسکرین استفاده کنیم. اینجا من با دو تا مشکل دیگه روبه‌رو بودم.۱- لازم داشتم که تنها از یک پنجره‌ی خاص (پنجره‌ی پخش کلاس) رکورد بگیرم.تا بتونم حین اون به کارهای دیگم برسم. یعنی لازم نباشه کل مدت، کلاس رکورد شده روی صفحه باشه. :/۲- صدای کلاس آنلاین روی سیستم پخش نشه و بتونم از اسپیکرهام استفاده‌ی مفیدتری بکنم. :)حالا بریم به راه‌حل‌هایی که پیدا کردم بپردازیم.اسکرین رکورد یک پنجره‌ی (Window) خاصبرای این کار به سراغ یکی از معروف‌ترین و پرطرفدارترین نرم‌افزارهای رایگان Screen recorder‌ یعنی نرم‌افزار OBS رفتم. OBS نرم‌افزار خیلی قدرتمندی هست و توضیحاتش رو می‌تونید با یه سرچ ساده پیدا کنید،‌ این صفحه هم میتونه بهتون کمک کنه. برای ضبط یک پنجره‌ی خاص به‌صورت زیر عمل می‌کنیم: ۱- نرم‌افزار OBS رو باز می‌کنیم و در نوار پایین و در بخش Sources روی به‌علاوه (آیکون +) کلیک می‌کنیم.۲- در نوار باز شده روی Window Capture کلیک می‌کنیم.۳- در پنجره‌ی باز شده می‌تونید برای Source‌ای که اضافه کردید اسمی بذارید، روی Ok کلیک می‌کنیم.۴- در پنجره‌ی جدید باز شده، در قسمت Window پنجره‌ی مورد نظر را انتخاب می‌کنیم. در قسمت Capture Method نیز گزینه‌ی BitBit را انتخاب می‌کنیم.نکته ۱: در صورتی که Capture Method در حالت اتوماتیک باشد، تمامی حرکات نشانگر موس شما در هر پنجره‌ای که باشید رکورد می‌شود. برای جلوگیری از این امر از گزینه‌ی ‌BitBit استفاده می‌کنیم. در این حالت و با فعال بودن گزینه‌ی Capture Cursor تنها زمانی که در پنجره‌ی مورد نظر قرار داشته باشید، حرکت نشان‌گر رکورد خواهد شد.نکته ۲: برای اینکه نکته قبلی عمل بکند باید در مرورگر خودتون «Hardware acceleration» رو غیرفعال کرده باشید.۵- روی گزینه‌ی Ok‌ کلیک می‌کنیم.تنظیم نرم‌افزار OBS‌ برای رکورد یک صفحه‌ی خاصنکته‌ی مهم: در تمام مدت رکورد، پنجره‌ی مورد نظر باید باز باشه و نباید Minimize بشه (ولی لازم نیست که کل مدت، کلاس رکورد شده در حال نمایش باشه).آزادسازی اسپیکرها!خب، برای این منظور نیاز داریم که بتونیم کانال‌های صدایی‌ که در سیستم پخش می‌شن رو جدا کنیم و کانال صدای کلاس مجازی رو به‌صورت Virtual جدا کنیم و به OBS بدیمش. برای اینکار ابتدا نیاز هست که نرم‌افزار Voicemeter رو نصب کنیم. پس از نصب این نرم‌افزار شما می‌تونید یک کانال خروجی Virtual داشته باشید.برای راه‌اندازی این نرم‌افزار به‌صورت زیر عمل می‌کنیم:نرم‌افزار Voicemeter‌ را باز می‌کنیم. در بالا سمت راست نرم‌افزار از شما خواسته می‌شود سخت‌افزار صدای خروجی خود را انتخاب کنید (این قسمت با یک نوشته‌ی قرمز مشخص می‌شود). روی A1 کلیک کنید و گزینه‌ی ...:MME (که ... نام سخت‌افزار صدای خروجی است) را انتخاب کنید.حال در مرحله‌ی اول، باید صدای خروجی از کلاس آنلاین را به Voicemeter انتقال دهیم. برای این منظور می‌توان از نرم‌افزارهایی نظیر EarTrumpet استفاده کرد. اما خبر خوب این است که اگر آخرین نسخه‌ی سیستم عامل ویندوز ۱۰ را داشته باشید نیازی به نصب هیچ نرم‌افزاری ندارید. برای این کار کافیه که به صورت زیر عمل کنید:۱- وارد تنظیمات صدای سیستم (Sound Settings) شوید.۲- در انتهای پنجره و در بخش Advance sound options روی گزینه‌ی ...App volumes and کلیک کنید.۳- در صفحه وارد شده، Output صدای مورد نظر را روی Voicemeter‌ قرار می‌دهید.تنظیم Output خروجی صدای مورد نظرحال باید صدای ورودی را در نرم‌افزار Voicemeter‌ و در بخش Virtual Input مشاهده کنید. در این بخش دو گزینه‌ی A‌ و B برای صدای خروجی وجود دارد. با انتخاب حالت A، صدا به‌خروجی اصلی یعنی اسپیکرهای شما انتقال داده می‌شود و با انتخاب حالت B، صدا به خروجی Virtual هدایت می‌شود. همچنین لازم به ذکر هست که این دو گزینه می‌توانند همزمان فعال باشن.حال باید نرم‌افزار OBS را تنظیم کنیم که صدا را از Voicemeter بگیرد. برای اینکار به‌صورت زیر عمل می‌کنیم:۱- نرم‌افزار OBS رو که باز می‌کنیم. در نوار پایین و در بخش Sources روی به‌علاوه (آیکون +) کلیک می‌کنیم.۲- در نوار باز شده روی Audio Output Capture کلیک می‌کنیم.۳- در پنجره‌ی باز شده می‌تونید برای Source‌ای که اضافه کردید اسمی بذارید، روی Ok کلیک می‌کنیم.۴- در پنجره‌ی جدید باز شده و در قسمت Device گزینه‌ی Voicemeter input را انتخاب می‌کنیم.رکورد بی‌دردسر!پس از طی مراحل گفته شده، صدای کلاس نباید توسط اسپیکرهاتون پخش بشه ولی باید در نرم‌افزار Voicemetert و همچنین در بخش Audio Mixer‌ نرم‌افزار OBS‌ و در نوار صدای Desktop Audio قابل مشاهده باشه.برای شروع عملیات رکورد کافیه در بخش Controls روی Start Recording کلیک کنید. با توجه به اینکه نباید پنجره‌ی مورد نظر رو Minimize کنید پیشنهاد من این هست که برای اینکار یک دسکتاپ جدید درست کنید (+). جابه‌جایی بین دسکتاپ‌ها خیلی راحت و با کلید‌های ترکیبی Ctrl + Windows + Right/Left Arrow key انجام میشه. همچنین من برای هر رکورد تایمری هم قرار می‌دادم تا از اتمام رکورد مطلع بشم.البته برای این منظور، خود نرم‌افزار نیز قابلیتی را فراهم کرده است، از منوی Tools گزینه‌ی Outout Timer را انتخاب کنید و زمان مورد نظر خوردتون رو در قسمت Stop recording after وارد کرده و گزینه‌ی استارت را بزنید.قاعدتا باید پس از اتمام هم گزینه‌ی Stop Recording را بزنید و فایل رکورد شده را می‌تونید از مسیر File و گزینه‌ی Show Recordings ببینید.نکته‌ی دیگری که باید اشاره کنم این هست که برای اطمینان از رکورد درست هر کلاس قبل از اون حتمن صفحه‌ی آرشیو جلسات را یک بار Refresh‌ کنید. این کار برای اطمینان از این هست که در سیستم ورود کردید و سیستم شما را به‌دلیل عدم فعالیت خارج نکرده باشد.در متن این نوشته از کلمه‌ی «رکورد» بدون ترجمه‌ی آن به «ضبط» استفاده کردم تا ملموس‌تر باشه.این پست، قسمت سوم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه‌ی این کار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسین ستاریان</author>
                <pubDate>Sat, 16 May 2020 02:56:00 +0430</pubDate>
            </item>
                    <item>
                <title>چای ۲: دسترسی به کنسول مرورگر در موبایل</title>
                <link>https://virgool.io/internerds/tea-2-browser-console-mobile-v0n6vyotwtdt</link>
                <description>شاید کلا چندبار، ولی پیش‌اومده که بخوام وقتی یک سایت رو روی موبایل واقعی تست می‌کنم، بتونم المان‌ها رو inspect کنم یا کنسول (console) رو چک کنم. خوشبختانه برای اینکار راه‌حل‌هایی وجود داره که در ادامه بررسی می‌کنیم، اما لازم به ذکره، چندان راحت نیستن!پروژه Erudaنمونه استفاده از Erudaبرای استفاده از Eruda، باید اسکریپت اون به سایت اضافه بشه. برای اینکار می‌تونیم اسکریپت زیر رو در آدرس‌بار وارد کنیم:javascript\:(function () { var script = document.createElement(&#039;script&#039;); script.src=&amp;quot//cdn.jsdelivr.net/npm/eruda&quot; document.body(script); script. = function () { eruda.init() } })();توجه کنید که قسمت :\javascript رو به :javascript تغییر بدین (\ رو حذف کنین).به دلیل محدودیت ویرگول مجبور به اضافه این کاراکتر شدم تا تمامی اسکریپت به درستی نمایش داده بشه.برای اینکه هردفعه مجبور به اینکار نباشیم و راحت‌تر استفاده کنیم، پیشنهاد خودشون اضافه کردن اسکریپت بالا به‌‌صورت بوکمارکلت (Bookmarklet) هست تا با اجرای اون Eruda به صفحه اضافه بشه. برای اینکار، کافیه این اسکریپت رو با نامی که دوست دارین Bookmark کنین و دفعه بعدی برای اجرای اون فقط از آدرس‌بار این بوکمارک رو انتخاب کنین.استفاده از Remote debuggingاستفاده از این روش چهار محدودیت داره: تنها برای گوشی‌های اندروید و مرورگر کروم قابلیت استفاده داره، برای اون نیاز هست تنظیمات مربوط به توسعه‌دهندگان (Developers Options) موبایل فعال شود و لازم است موبایل با استفاده از کابل به سیستم وصل شود.برای فعال کردن Developer Options، وارد تنظیمات موبایل شده و از منوی About phone یا مشابه آن، گزینه مربوط به Build number را پیدا کنید و روی آن چندین بار تپ (tap) کنین تا این تنظیمات فعال شود.سپس وارد Developer options بشین و گزینه مربوط به USB debugging رو فعال کنین.در ضمن، توجه کنید که اگر از برنامه‌های سازنده رمز یکبار مصرف (OTP) استفاده می‌کنید، ممکن است پیغام خطا و یا درخواست خاموش کردن این تنظمیات را دریافت کنین.بعد از اینکه تنظیمات توسعه دهندگان (همینطور USB debugging) رو فعال کردید، موبایل رو با استفاده از کابل به سیستم وصل کنین در صورتی که پیغامی مربوط به دسترسی در موبایل ظاهر شد، اجازه آن را بدهید و وارد آدرس زیر بشین:chrome://inspectدر این صفحه در قسمت Remote Target دستگاه‌های شناخته شده را به همراه وضعیت اتصال و تب‌های (tab) مرورگر کروم دستگاه مشاهده می‌کنید:همونطور که احتمالا می‌بینین، قابلیت دسترسی به کنسول service workerها هم امکان پذیره.صفحه chrome://inspectحال آدرس دلخواه خود را باز کرده و گزینه inspect مقابل نام آن تب را انتخاب کنین.با استفاده از input که مقابل اسم دستگاه می‌بینید می‌تو‌نین برای باز کردن یک تب جدید در آدرس دلخواه استفاده کنین. توجه کنین که مرورگر کروم روی موبایل باز باشد.نمونه inspect با استفاده از remote debugging+ مشاهده‌ی پروژه‌های localیکی از ویژگی‌های جالب دیگه کروم امکان به اشتراک گذاری یک پورت داخلی با استفاده از Port forwarding هست. با استفاده از این روش می‌تونیم پروژه‌ای که روی سیستم برای مثلا روی پورت ۳۰۰۰ در حال اجراست رو  به یکی از پورت‌های موبایل متناظر (map) کنیم تا بتونیم پروژه رو مستقیم داخل موبایل مشاهده کنیم.برای اطلاعات و گزینه‌های بیشتر می‌تونید پست «چگونه یک لوکال سرور ران کنیم؟ اند مور» رو مشاهده کنین.برای اینکار از روی گزینه Port forwarding در بالای کلیک کرده و در سمت چپ پورت مورد نظر روی سیستم و در سمت راست آدرس مورد نظر برای دسترسی به این پورت را وارد کنید:اگر آدرس مشخصی مد نظر ندارید، localhost:3000 و یا با پورت مشابه را انتخاب کنید.نمونه استفاده از port forwardingحالا می‌تونین روی موبایل به این آدرس (localhost:3000) برین و برنامه‌ای که اجرا بود رو مشاهده کنین.این پست، قسمت دوم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه اینکار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Fri, 15 May 2020 03:49:01 +0430</pubDate>
            </item>
                    <item>
                <title>چای ۱: بروزرسانی Google Sheets با استفاده از پایتون</title>
                <link>https://virgool.io/internerds/tea-1-googlesheets-python-fixw1jmvrjx6</link>
                <description>استفاده از Google sheets در کنار پایتون، امکانات و‌ انعطاف‌پذیری خیلی خوبی به توسعه‌دهندگان برای انجام کارها میده، برای مثال اگر می‌خواین درصد پیشرفت یک پروسه (process) رو به صورت اتومات داخل spreadsheet بروز کنید تا بتونین با استفاده از چارت نمایش بدین، یا اطلاعات یک Sheet رو برای محاسبات آماری داخل Jupyter NoteBooks وارد کنید، و یا حتی، یک دیتابیس ساده و سریع می‌خواین که اعمال CRUD رو پشتیبانی کنه، استفاده از google sheets گزینه سریع و راحتیه. در این پست، ‌به عنوان اولین قسمت چای، با استفاده پایتون و gspread کتابخونه‌ای که Anton Burnashev توسعه داده تنها توی چند خط کد، روی Google Sheets داده اضافه، ویرایش و حذف می‌کنیم. قبل از شروع، موارد زیر رو آماده کنین:پیش‌نیاز‌هاپایتون ۲.۶+ یا ۳+مدیر بسته pipیک حساب‌کاربری Google و یک Google Sheet که باهاش کار کنیم.برای شروع می‌تونید از این Sheet که در این آموزش استفاده می‌کنم، استفاده کنید. کافیه لینک رو باز کنید و اون رو کپی کنید:نحوه ایجاد کپی از Sheet مورد استفاده این پستاحراز هویتبرای دسترسی به spreadsheetتون روی Google Sheets به‌صورت برنامه‌نویسی شده، نیاز دارید تا از  Google API Console یک سرویس و گواهی‌نامه OAuth2 دریافت کنید. برای اینکار قبل از هرکار نیاز است یک پروژه ایجاد کنیم، برای ایجاد پروژه  وارد کنسول بشین و مطابق مراحل زیر یک پروژه ایجاد کنید:روی Create Project کلیک کنید.نام پروژه رو انتخاب کنید.روی Create کلیک کنید.ساخت پروژه جدید در Google API consoleبرای دسترسی به Google Sheet‌s نیاز است سرویس‌های Google Drive API و Google Sheets API را به ترتیب فعال کنیم. برای اینکار وارد کنسول خود شده و روی دکمه ENABLE APIS AND SERVICES کلیک کنید و هرکدام از موارد گفته شده را جستجو کرده و روی Enable کلیک کنید.همچنین می‌توانید روی لینک هرکدام در همین پست کلیک کرده و آن‌ها را Enable کنید.اگر دکمه Enable برای شما غیر فعال است، احتمالا پروژه ساخته نشده‌است. از اجرای درست مرحله قبل مطمئن شوید و یا تا زمانی که پروژه کامل ساخته شود، صبر کنید.بعد از فعال شدن Google Sheet API، به داشبوردتون منتقل می‌شین، حالا مطابق مراحل زیر تنظیمات API را انجام دهید تا یک ربات با اختیارات لازم برای کار با spreadheetمون بسازیم: در صفحه داشبورد، روی Create Credentials کلیک کنید.اگر این گزینه را پیدا نکردین از منوی سمت چپ وارد بخش Credentials شده و روی گزینه CREATE CREDENTIALS و سپس گزینه آخر کلیک کنید:ایحاد اعتبارنامه (Credential) جدیداز منوی اول (نوع API)، مورد Google Sheet API را انتخاب کنید.از منوی دوم (نوع دسترسی)، گزینه Web server را انتخاب کنید.در قسمت بعدی (دسترسی مورد نیاز)، گزینه Application Data رو انتخاب کنید.در قسمت بعدی (استفاده از سرویس‌های ابری گوگل)، گزینه No را انتخاب کرده و روی دکمه آبی‌رنگ کلیک کنید.در صفحه بعد، یک نام به این Service Account داده و Role مربوطه را برابر Project/Editor قرار دهید.یک service account را می‌توان به صورت یک ربات با یک اکانت Google تصور کرد که با تنظیماتی که کردیم، تنها به Google Sheetsای که اضافه شود دسترسی دارد.فعال کردن سرویس Google Sheets APIپس از اتمام مراحل، یک فایل json دانلود می‌شود که نام آن را client_secret.json می‌گذاریم و در ادامه از آن برای احراز هویت استفاده می‌کنیم. این فایل رو باز کرده و Email مربوط به ربات (service account) رو پیدا و کپی کنید، سپس به Google Sheet مورد نظرتون برید و اون Sheet رو با این ربات اشتراک بذارین.اضافه کردن ایمیل ربات به Google Sheets خواندن اطلاعات Spreadsheetپس از تنظیم دسترسی‌ها و گواهی‌نامه‌های (credentials) لازم، حالا می‌تونیم با استفاده از پایتون به Sheet مورد نظر دسترسی داشته باشیم.برای اینکار درواقع به رباتی که در مرحله قبل به Sheet اضافه کردیم فرمان می‌دهیم.برای ادامه به دو پکیج پایتونی نیاز داریم:پکیج oauth2client برای احراز هویت توسط OAuth2.0 (اختیاری)پکیج gspread برای کار با Google Sheetsاین پکیج‌ها با استفاده از pip به‌راحتی نصب می‌شوند:توجه‌کنید که، بهتر است قبل از نصب آن‌ها یک محیط مجازی برای این پروژه بسازیم و بعد اقدام به نصب کنیم. (اختیاری) pip install gspread oauth2clientسپس یک فایل پایتون (برای مثال spreadsheet.py) ساخته و کد زیر را کپی کنید:import gspread

# Find a workbook by name and open the first sheet,
# Make sure you use the right name here.
client = gspread.service_account(filename=&#039;client_secret.json&#039;)
sheet = client.open(&amp;quotvirgool_template&amp;quot).sheet1

# Extract and print all of the values
list_of_records = sheet.get_all_records()
print(list_of_records)حال، مقادیر زیر را در کد، مطابق اطلاعات Sheet خودتون تغییر بدید:فایل client_secret.json باید در کنار این فایل قرار داشته باشد. برای استفاده از آن در مکان دیگر آدرس را در خط ۵ تغییر دهید.مقدار  virgool_template در خط ۶ را برابر نام Sheet بذارید (اگر از همین Sheet استفاده می‌کنید نیازی به تغییر نیست).مقدار sheet1 در همان سطر را مطابق صفحه مورد نظر خود تغییر دهید. (اختیاری) حال کد مورد نظر را اجرا کنید:python3 spreadsheet.pyمشاهده می‌کنیم که اطلاعات Sheet به صورت لیستی (List) از دیکشنری‌ها (Dictionaries) ‌چاپ می‌شود:نتیجه خواندن اطلاعات Google Sheet در اینجا ما اطلاعات Sheet را به‌صورت یک لیست از دیکشنری‌‌ها دریافت کردیم که هر کدام از المان‌های این دیکشنری‌ها مطابق یکی از ستون‌های جدول در Sheet است و در هر جدول اولین سطر به عنوان header در نظر گرفته می‌شود (در جدول ما Title و ...).اگر بخواهیم اطلاعات را به‌صورت لیستی از لیست‌ها دریافت کنیم می‌توانیم از متد زیر استفاده کنیم:sheet.get_all_values()همینطور، اگر تنها داده‌های یک سطر، ستون و یا سلول خاص از جدول را بخواهیم، می‌توانیم از متد‌های زیر استفاده کنیم:# Getting data for a cell by (row, column) indices 
sheet.cell(1, 1).value  

# Getting data for a cell using A1 notation 
sheet.acell(&#039;A1&#039;).value

# Getting data for a row by index
sheet.row_values(1)

# Getting data for a column by index
sheet.col_values(1)اضافه‌کردن، ویرایش و حذف اطلاعات Spreadsheetبرای نوشتن در یکی از خانه‌های جدول می‌توانیم از متد update_cell به‌صورت زیر استفاده کنیم:# update cell using row and column coordinates
sheet.update_cell(1, 1, &amp;quotI just wrote to a google sheet using Python, amazing!&amp;quot)

# update cell using A1 notation
worksheet.update(&#039;B1&#039;, &#039;Bingo!&#039;)به عنوان نمونه، در مثال زیر ‌مقدار پیشرفت Task3 در جدولمان را هر ثانیه ۱۰ درصد افزایش می‌دهیم:نمونه بروزرسانی مقدار یک سلول در جدولبه‌صورت مشابه، برای اضافه کردن یک سطر به جدول:row = [&amp;quotI&#039;m&amp;quot, &amp;quotinserting&amp;quot, &amp;quota&amp;quot, &amp;quotrow&amp;quot, &amp;quotinto&amp;quot, &amp;quota,&amp;quot, &amp;quotgoogle sheet&amp;quot, &amp;quotwith&amp;quot, &amp;quotPython&amp;quot]
index = 10
sheet.insert_row(row, index)برای پاک‌کردن محتویات یک سلول می‌توانیم محتویات آن را برابر یک رشته (String) خالی (&quot;&quot;) قرار دهیم،‌ اما برای پاک‌کردن یک ردیف از جدول،‌ می‌توانیم از متد delete_row استفاده کنیم:sheet.delete_rows(10)توجه‌کنید که متد‌هایی که بررسی کردیم،‌ تنها بخش کوچکی از کتابخانه gspread هستند، برای اطلاعات بیشتر و آشنایی با باقی متد‌ها، مستندات آن را بخوانید.کتابخانه gspread توی ورژن‌های جدیدش عمل احراز هویت رو به‌صورت خودکار انجام میده،‌ اما پیش از این نیاز بود تا خود کاربر اینکار رو انجام بده. از اونجایی که ممکنه با کد‌هاش مواجه بشین، روش انجام کار بدین صورت بود:import gspread
from oauth2client.service_account import ServiceAccountCredentials

# use creds to create a client to interact with the Google Drive API
scope = [&#039;https://spreadsheets.google.com/feeds&#039;, &#039;https://www.googleapis.com/auth/drive&#039;]
creds = ServiceAccountCredentials.from_json_keyfile_name(&#039;client_secret.json&#039;, scope)
client = gspread.authorize(creds)

# Find a workbook by name and open the first sheet,
# Make sure you use the right name here.
sheet = client.open(&amp;quotvirgool_template&amp;quot).sheet1

# Extract and print all of the values
list_of_records = sheet.get_all_records()
print(list_of_records)منابع‌ویدیو معرفی Jupyter Notebooks از Andrew Ng مدرس استنفورد و موسس deeplearning.aiاین پست از وبلاگ twilio مستندات gspreadاین پست، قسمت سوم از چای، مجموعه‌ای در باب «چیزی که امروز یادگرفتم» است. باقی چای‌ها رو می‌تونید از اینجا مشاهده کنید و در مورد فلسفه‌ی این کار بخونید.</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Thu, 14 May 2020 19:42:32 +0430</pubDate>
            </item>
                    <item>
                <title>چای: چیزی که امروز یادگرفتم.</title>
                <link>https://virgool.io/internerds/tea-0-s29w12brbfyn</link>
                <description>چیزی که امروز یاد‌گرفتم، یا «چای» یک مجموعه پست هست که من و حسین قراره دنبال کنیم و توی اون چیزهای جدیدی که یاد میگیریم رو منتشر کنیم.داستان از اینجا شروع شد که مدت‌ها قبل ریپازیتوری til از Josh Branchaud رو دیده بودم که ایده جالبی داره، به اشتراک گذاری چیزهایی که امروز یادگرفتم! توی این ریپازیتوری Josh یک سری مطلب منتشر می‌کنه با عنوان TIL یا درواقع Today I learned که هدف از این مجموعه اینه که موارد کوچیکی که نکته‌خاصی دارن یا بعدا مجدد استفاده می‌شن و بخاطر کوچکی نیازی به یک بلاگ پست ندارن رو به اشتراک بذاره.مدت‌ها گذشت و احتمالا اون هم در کنار خیلی‌های دیگه تو قبرستون tabهایی که نگه داشتم تا بعدا ببینم گم شد، تا اینکه چندوقت پیش که طبق عادت داشتم نگاه می‌نداختم به فید‌های daily.dev، چشمم به یکی از پست‌های Remy Sharp خورد که توی اون می‌خواست نحوه مدیریت TILهاش رو آموزش بده. همونطور که خودش می‌نویسه که وقتی این ایده رو دیدم گفتم منم میخوام همچین چیزی درست کنم، من و حسین هم به فکر افتادیم که یک مجموعه مشابه با Today I Learned منتشر کنیم که هیچ قانونی برای زمان انتشار، حجم آموزش و موضوعش نداشته باشه و توی اون چیز‌های مختلفی که یاد میگیریم رو منتشر کنیم،‌ تا هم خودمون بعدا بتونیم استفاده کنیم و هم دیگران.چای، اسمی هست که برای این مجموعه انتخاب کردیم، چون اختصاری برای چیزی که امروز یادگرفتم هست و مضمونی که ما دنبالش بودیم رو می‌رسونه.تصویرسازی از Austin Scottiدر ادامه لیست چای‌هایی که تا الان منتشر شده میاد و آپدیت میشه.چای ۱: بروزرسانی Google Sheets با استفاده از پایتونچای ۲: دسترسی به کنسول مرورگر در موبایلچای ۳: چطوری کلاس‌های مجازی دانشگاه رو ضبط کنم؟چای ۴: خودکارسازی تلگرام، دانلود مدیا‌های یک کانال/گروهچای ۵: اسکریپت نویسی Shell، بازه‌ها در حلقه forچای ۶: پنهان‌کردن عمدی فایل‌ها در لینوکسچای ۷: اجرای دستورات قبلی در ترمینالچای ۸: بریدن و چسباندن ویدیو‌ها بدون خونریزیچای ۹: تبدیل GeoJSON به SVG با استفاده از D3چای ۱۰: رفع مشکل No Audio Output Deviceچای ۱۱: حل مشکل نگاشت پورت‌های WSL 2چای ۱۲: فرمت‌دهی ویدئو برای Video Strickerهای تلگرام با استفاده از FFmpeg</description>
                <category>اینترنردز</category>
                <author>محمدحسن ستاریان</author>
                <pubDate>Thu, 14 May 2020 18:49:30 +0430</pubDate>
            </item>
                    <item>
                <title>سینما - جنگ ستارگان را به چه ترتیبی ببینیم؟</title>
                <link>https://virgool.io/internerds/%D8%B3%DB%8C%D9%86%D9%85%D8%A7-%D8%AC%D9%86%DA%AF-%D8%B3%D8%AA%D8%A7%D8%B1%DA%AF%D8%A7%D9%86-%D8%B1%D8%A7-%D8%A8%D9%87-%DA%86%D9%87-%D8%AA%D8%B1%D8%AA%DB%8C%D8%A8%DB%8C-%D8%A8%D8%A8%DB%8C%D9%86%DB%8C%D9%85-i1gu03whefwb</link>
                <description>این مطلب را پیش‌تر توی وب‌سایتم نوشته بودم؛ امروز بخاطر دیدن قسمت آخر این سری گفتم اینجا هم منتشرش کنم. این نکته رو هم بگم که با توجه به اینکی چندسالی از انتشارش می‌گذشت لازم دیدم یه ‌جاهایی رو ادیت کنم.– توجه: این پست ممکنه شامل اسپویل هایی  از این مجموعه باشه. البته تا بتونم سعیمو میکنم نباشه. با اینکه این  مجموعه ماله ۳۰ و خورده ای سال پیشه ولی بازم گفتم بگم ?یکی از اولین سوال‌هایی که زمان شروع دیدن سری فیلم‌های جنگ ستارگان یا به‌طور درست‌تر جنگ‌های ستاره‌ای ممکنه براتون پیش بیاد اینه که به چه ترتیبی این  فیلم‌ها رو تماشا کنید.قبل هر چیز بیاید یکم درباره قسمت‌ها صحبت کنیم تا ببینیم اصلا چرا این سوال پیش میاد.این مجموعه به سه سه‌گانه تقسیم بندی می‌شه:۱- سه‌گانه اصلی یا Original trilogy         • جنگ ستارگان قسمت چهارم: امیدی تازه – ۱۹۷۷         • جنگ ستارگان قسمت پنجم: امپراتوری ضربه می‌زند – ۱۹۸۰         • جنگ ستارگان قسمت ششم: بازگشت جدای – ۱۹۸۳۲. سه‌گانه پیشین یا Prequel trilogy   • جنگ ستارگان اپیزود اول: تهدید شبح – ۱۹۹۹   • جنگ ستارگان اپیزود دوم: حمله کلون‌ها – ۲۰۰۲   • جنگ ستارگان اپیزود سوم: انتقام سیت – ۲۰۰۵۳. سه‌گانه پسین یا Sequel trilogy   • جنگ ستارگان اپیزود هفتم: نیرو برمی‌خیزد – ۲۰۱۵   • جنگ ستارگان اپیزود هشتم: آخرین جدای – ۲۰۱۷   • جنگ ستارگان اپیزود نهم: خیزش اسکای‌واکر – ۲۰۱۹سه‌گانه اصلی، داستان انحطاط امپراتوری توسط لوک اسکای‌واکر هست.  سه‌گانه پیشین (سه‌گانه دوم منتشر شده)، درباره داستان زندگی آناکین اسکای‌واکر، پدر لوک هست و  سه‌گانه پسین درباره اتفاقات ۳۰ سال پس از سه‌گانه اصلی هستش.حالا با توجه به قسمت‌ها و سال پخش و داستانشون می‌شه این مجموعه رو یا به ترتیب انتشار یعنی بصورت:IV V VI I II IIIو یا به ترتیب داستان یعنی بصورت:I II III IV V VIمشاهده کرد. اعداد گذاشته شده به شماره اپیزود براساس سیر داستانی مربوط است. موقع انتشار سری اول این فیلم‌ها از این اعداد استفاده نمی‌شده ولی بعد پایان سری دوم شماره اپیزودها به نام اون‌ها اضافه شد.ترتیبی که من خودم ترجیح دادم استفاده کنم ترتیب انتشار بود تا همون  چیزی که مردم در سینماها دیدین و براش سال‌ها صبر کردن رو بتونم تجربه کنم و  پیشنهاد می‌کنم شما هم با همین ترتیب شروع به دیدن کنید.اما چیزی که من رو واداشت تا این پست رو بنویسم دو ترتیب دیگه بود که تو  وبگردی چند روز پیشم پیدا کردم که برای دوباره دیدن این مجموعه و یا شاید برای بعضی که دوست دارن یکم متفاوت شروع به دیدن بکنن جالب باشه، ترتیب:IV V I II III VIو ترتیب نسبتاً جالب (!):IV V II III VIبه ترتیب اول اصطلاحا دنباله ارنست ریستر یا Ernest Rister sequence و به ترتیب دوم هم MacheteOrder می‌گن.درمورد دنباله ارنست ریستر گفته شده که این دنباله با دو قسمت ابتدایی سه‌گانه اصلی شروع و دقیقا زمانی که داستان به یک نقطه حساس می‌رسه که اولاً هان سولو گم میشه و دوماً لوک با یک حقیقت تلخ مواجه میشه، با فلش بک در سه  قسمت چیزهای بیشتری می‌فهمیم و در نهایت با اپیزود ششم مجموعه به پایانش  میرسه.چیزی که توی ترتیب دومی جالبه حذف کردن اپیزود ۱ هستش. چرا؟ چون از نظر خیلی‌ها کاملا بیخود هست و هیچ ربطی به بقیه داستان نداره. اپیزود ۱ یا همون «تحدید شبح» داستان نه سالگی آناکین اسکای‌واکر هست و  درواقع اولین روبه‌رویی ما با او در سیر زمانی (نمیدونم گرفتید یا نه!) و  به نظرم تنها موضوع مهمی که درش گفته میشه، نحوه آشنایی آناکین و پادمه و چگونگی شاگرد اوبی وان شدن آناکین هست. همین! و خودم به شخصه در قسمت دوم، تغییر شخصیتی زیادی رو تو این شخصیت حس کردم و به نظرم قسمت یک مقدار زیادی نالازمه.در آخر اینم بگم که اپیزودهای دیگه یعنی سه‌گانه پسین (Sequel) همگی در ادامه قسمت ششم می‌تونن دیده شن.امیدوارم این پست به دردتون بخوره و خوشحال می‌شم شما هم بگین به چه ترتیبی این مجموعه بی‌نظیر رو دوست دارید؟منابع (+) (+) (+) برای اطلاعات خیلی خیلی بیشتر و یکم نردی‌تر پیشنهاد می‌کنم این دو صفحه رو حتماً یه نگاهی بندازین.۱- یک اینفوگرافی در مورد ترتیب آخر (+)۲- درباره لغات بکار رفته در این پست مثل دنباله، پیشین (Prequel)، پسین (Sequel) و لغاتی از این دست که ممکنه در جاهای دیگه ببینین دوست دارم پست‌‌هایی با مضمون لغت‌شناسی و یا اصطلاحات سینمایی بنویسم نظرتون چیه؟</description>
                <category>اینترنردز</category>
                <author>محمدحسین ستاریان</author>
                <pubDate>Sun, 22 Mar 2020 22:23:58 +0430</pubDate>
            </item>
                    <item>
                <title>بخواب تا به یادآوری، به یاد داشته باش تا بخوابی</title>
                <link>https://virgool.io/internerds/%D8%A8%D8%AE%D9%88%D8%A7%D8%A8-%D8%AA%D8%A7-%D8%A8%D9%87-%DB%8C%D8%A7%D8%AF%D8%A2%D9%88%D8%B1%DB%8C-%D8%A8%D9%87-%DB%8C%D8%A7%D8%AF-%D8%AF%D8%A7%D8%B4%D8%AA%D9%87-%D8%A8%D8%A7%D8%B4-%D8%AA%D8%A7-%D8%A8%D8%AE%D9%88%D8%A7%D8%A8%DB%8C-ymui5nurr3wb</link>
                <description>این پست رو سال پیش برای کانال انجمنمون نوشته بودم گفتم اینجا هم بذارم :)یکی از پدیده‌هایی که برای مهندس‌های مواد خیلی مهمه و هروقت دلیل اتفاقی رو ندونن همه چیز رو می‌اندازن گردنش، پدیده‌ی نابجایی‌ها هستش. مثلا دانشمندان خیلی قبل از اینکه بتونند ساختار مواد رو با میکروسکوپ مشاهده کنند دلیل شکست مواد رو وجود عیوبی در ساختار اون‌ها می‌دونستند.اگه بخوایم پدیده‌ای مشابه رو در مطالعاتی که روی مغز انسان به‌خصوص درباره‌ی خواب دیدن و حافظه، انجام شده داشته باشیم، اون چیزی که توجه‌ها اول میره سمتش چیزی به اسم REM یا Rapid-eye-movement  هستش. این پدیده، یکی از مراحل ۴ گانه‌ی خواب انسان هست و توی اون همونطور که از اسمش مشخصه حرکت سریع چشم‌ها رو داریم. در واقع، در این حالت مغز انسان برخلاف بدنش بیداره و مهم‌ترین کاری که در این مرحله از خواب اتفاق میوفته جابه‌جایی اطلاعات از حافظه‌ی کوتاه مدت به بلند مدت هستش.فرض کن که الان ساعت ۱۰ شبه و فردا صبح زود یک امتحان سخت داری ولی هنوز فکر می‌کنی خوب آماده نیستی. کاری که می‌تونی بکنی اینه که به‌ زور قهوه و چوب کبریت (!) خودت رو بیدار نگه‌داری یا ... کار بهتری بکنی و بری بخوابی!خواب تقریبا یک سوم زندگی ما رو تشکیل میده و ما به طرز عجیبی اهمیت کمی به اون می‌دیم. خواب از دست دادن زمان و یا کاری که باید بعد از تموم شدن همه کارامون انجام بدیم نیست، بلکه عملی حیاتی برای برقراری تعادل جسمی و روحی در فرآیندهای مهمی مثل رشد یا پاسخ‌های حفاظتی بدن هستش.یکی از عملیات‌های خیلی مهم دیگه‌ای که موقع خواب توی مغز صورت می‌گیره، عمل بازسازی هستش که برای حافظه‌ امری حیاتی به‌شمار میاد. این عملیات در هیپوکمپوس مغز اتفاق میوفته و به زبان ساده با قوی‌تر کردن اطلاعات دریافتی از حافظه کوتاه مدت، اون‌ها رو به حافظه بلند مدت انتقال میده. موارد زیادی هست که روی حافظه تاثیر گذاره مثلا ترس، استرس یا موقعیتی احساسی اما یکی دیگر از فاکتورها، همونطور که حدس زدید، خواب هستش.مراحل چهارگانه خوابگفتیم که خواب شامل ۴ مرحله هست، دو مرحله آخر که اصطلاحا بهشون Nrem (یا No-rem) و Rem گفته میشه، بخش‌های عمیق‌تر خواب هستند که عملیات بازسازی در آن‌ها انجام میشه. در مرحله سوم اطلاعات حافظه آشکار یا declarative memory در بخش داخلی هیپوکمپوس ذخیره شده و به حافظه بلند مدت منتقل میشه. در مرحله چهارم همین اتفاق برای اطلاعات مربوط به حافظه رویه‌ای یا procedural memory، مواردی که طی تکرار فراگرفته میشن مثل نحوه نواختن یک آهنگ با پیانو، میوفته.پس طی مطالعات ایده‌آل‌ترین حالت خوابیدن ۳ ساعت بعد از حفظ کردن فرمول‌هاتون و ۱ ساعت بعد از تمرین مهارت‌هاتون هستش. در دوران امتحانات خیلی ها ممکنه خواب رو به بعد از امتحان موکول کنند ولی همونطور که گفته شد، با خوابیدن بعد از مطالعه به تثبیت اون‌ها تو حافظتون کمک بیشتری می‌کنین.منبع:‏(+) The benefits of a good night&#x27;s sleep </description>
                <category>اینترنردز</category>
                <author>محمدحسین ستاریان</author>
                <pubDate>Sat, 05 Oct 2019 11:24:43 +0330</pubDate>
            </item>
                    <item>
                <title>طراحی - داستان رنگ: بخش اول - چگونه رنگ مناسب پیدا کنیم؟ و یکم بیشتر</title>
                <link>https://virgool.io/internerds/aboutcolors1-skkofyn4wzmd</link>
                <description>یکی از مهم‌ترین نکات برای طراحی اینه که چطوری رنگ یا رنگ‌های مناسبی برای کارمون انتخاب کنیم که اون رنگ‌ها به‌قول معروف به هم بیان و هارمونی خوبی داشته باشن. برای این کار، یا می‌شه رفت تئوری‌های شناخت رنگ و روش‌‌ها و مدل‌های انتخاب رنگ‌ها رو خوند یا اینکه از سایت‌هایی که برای همین منظور ساخته شدن و پَلِت‌های رنگی (Color Palettes) پیشنهاد می‌کنن استفاده کنیم.تو این سری پست‌ها می‌خوام بعد یکم صحبت راجع‌به رنگ و معرفی لینک‌ها کاربردی برای شناخت خود داستان رنگ‌ها بیام چندتا از همین سایت‌ها که بهش اشاره شد رو معرفی کنم و نظر خودمو راجبشون بنویسم. ترتیب معرفی سایت‌ها هم از اونایی که بیشتر استفاده می‌کنم شروع میشه تا اوناییکه فقط جنبه معرفی دارن!سعی می‌کنم مطالبی که می‌نویسم، همش رو منبع یا لینکی برای مطالعه بیشتر بذارم پس شما هم به مطالب این پست‌ها اکتفا نکنین و یه سری به لینک‌ها بزنین.فقط اینم بگم که هر نظر یا انتقادی به نحوه نوشتن و مطالبی که بیان می‌کنم بود حتمن بهم بگین، ممنون.بخش اول: داستان رنگ‌هاداستان زندگی رنگ‌ها ارتباط خیلی نزدیکی به زبان آدم‌ها داره. زبان‌های توسعه یافته کلمات زیادی برای رنگ‌ها دارن اما زبان‌هایی هم پیدا می‌شن که کلمات کمتری برای رنگ‌ها داشته باشن. مثلا یکی از این زبان‌ها زبان Wobe هست که کلا ۳ تا کلمه برای رنگ داره؛ تیره، روشن و قرمز! یا مثلا توی کتاب ادیسه هومر خیلی واژگان محدودی برای رنگ‌ها بکار رفته و مثلا رنگی که برای خون، امواج دریا و شراب بکار رفته همگی یکی و یه چیزی تو مایه‌های بنفش بوده. حالا اینکه بررسی علمی این داستان چیه و چرا جای خود داره ولی نکته‌ای که باید بهش توجه بشه اینه که رنگ خیلی چیز قرار دادی می‌تونه باشه و اون چیزی که ما می‌بینیم ممکنه با چیزی که فرد دیگه‌ای میبینه متفاوت باشه مثل همون استریوتایپ معرف که اقایون نسبت به خانم‌ها رنگ‌های کمتری رو تشخیص می‌دن. [۱]روش‌های متنوعی برای انتخاب رنگ‌ها وجود داره که به چندتاش اشاره می‌کنم. اما قبل از اون برای پرداختن به این روش‌ها نیاز به آشنایی با چیزی به نام Color Wheel داریم. این چرخه از رنگ‌های اصلی (قرمز، آبی و زرد) شروع میشه و با ترکیب کردن اون‌ها کامل میشه تا جاییکه یک طیف پیوسته از رنگ‌ها داریم. حالا روی این چرخه رنگی میان یه سری رنگ‌ها رو گروه‌بندی می‌کنن.- رنگ‌های اصلی (Primary Colors): که همون سه رنگ قرمز، آبی و زرد هستند.- رنگ‌های ثانویه (Secondary Colors): رنگ‌هایی که از ترکیب سه رنگ اصلی به‌دست میان. نارنجی (ترکیب قرمز و زرد)، سبز (ترکیب آبی و زرد) و بنفش (ترکیب آبی و قرمز).- رنگ‌های ثالث یا میانه (Tertiary Colors): که از ترکیب رنگ‌های ثانویه به‌دست میان.حالا بعد آشنایی با چرخه رنگی بریم سراغ یه نکته دیگه، اساسا رنگ مانند هر چیز دیگری با یک سری پارامترها شناخته میشه. مهم‌ترین این پارامتر‌ها عبارتند از:- فام (Hue): که همون رنگ هست (اینکه مثلا آبی هست یا قرمز)- غلظت (Saturation): درجه خلوص اون رنگ- روشنایی (Brightness): میزان روشنایی رنگمطالعه بیشتر [۲]بخش دوم: روش‌های انتخاب رنگ‌ها۱- روش تک رنگ (Monochromatic color)در این روش از یک رنگ با غلظت‌ها و روشنایی‌های متفاوت استفاده می‌کنند. مثلا گرادیانی رو تصور کنین از سفید تا رنگی که مشخص کردین.۲- روش آنالوگ (Analogous colors)در این روش از رنگ‌های که در چرخه رنگی در کنار هم قرار دارند استفاده می‌کنند. مثلا آبی‌ها و سبزها یا قرمزها و نارنجی‌ها.۳- رنگ‌های مکمل (Complementary colors)این روش یکی از روش‌های پرطرفدار و معروف است. در این روش از رنگ‌های که در چرخه رنگ روبروی هم قرار دارند استفاده می‌کنند. مثل ترکیب‌های معروف آبی و نارنجی یا قرمز و سبز.۴- رنگ‌های مکمل جدا از هم (Split Complementary colors)این روش مانند روش قبل است با این تفاوت که از یک رنگ با رنگ‌های اطراف رنگ روبروی آن استفاده می‌کنند. این روش رنگ‌های بیشتری رو برای طراحی در اختیارمون می‌ذاره.۵- روش مثلثی (Triadic)در این روش از سه رنگ که فاصله یکسانی در چرخه رنگی دارند استفاده می‌کنند.۶- روش مستطیلی (Tetradic)در این روش از ۴ رنگ که دوبه‌دو مکمل هستند استفاده می‌شود. این روش برای طراحی‌هایی مناسب است که یک رنگ به عنوان رنگ اصلی و رنگ‌های دیگر به عنوان رنگ‌هایی برای تاکید (Accent) در اطراف اون مورد استفاده قرار می‌گیرند.مطالعه بیشتر [۳]بخش سوم: سیستم‌های رنگیبه‌طور کلی دو سیستم رنگی برای رنگ‌ها وجود داره، رنگ‌های کاهشی (Subtractive Colors) یا رنگ‌های افزایشی (Additive Colors). رنگ‌های افزایشی رنگ‌هایی هستند که از طریق صفحه‌های دیجیتال مثل تلویزیون، مانیتور، صفحه گوشی و یا پروژکتورها نشون داده می‌شن و ماهیتشون اینه که خود نور هست که به چشم ما وارد میشه و رنگ رو در چشم ما می‌سازه. این رنگ‌ها سه رنگ اصلی RGB  (به ترتیب سه رنگ قرمز، آبی و سبز) هستند. نکته قابل توجه برای این نام‌گذاری این هست که رنگ‌های افزایشی با سه رنگ RGB شروع شده و با افزودن رنگ بیشتر به سمت رنگ سفید می‌روند. مانند پیکسل‌های تشکیل دهنده تمام صفحات دیجیتال که اگه با ذره‌بین یا حتی با چشم از نزدیک دیده باشین از این سه رنگ تشکیل شده‌اند و روشن بودن هر سه رنگ، رنگ سفید و خاموش بودن هر سه، رنگ سیاه رو می‌سازه و باقی رنگ‌ها با ترکیب این سه رنگ تولید می‌شن.رنگ‌های کاهشی اما رنگ‌هایی هستند که در چاپ استفاده می‌شن. این رنگ‌ها از ۴ رنگ اصلی CMYK (به ترتیب سیان (Cyan)، مَجِنتا (Magenta)، زرد و سیاه) هستند. در چاپ اینجوری هست که رنگ پرینت شده توسط جوهرها روی کاغذ رو می‌بینیم و در حقیقت اون چیزی که رنگ رو تو چشم ما می‌سازه بازتاب نور حاصل از برخورد با جسم و رسیدن امواج جذب نشده از اون به چشم ما هست. پس چیزی که می‌بینیم خود امواج نور نیست (تصویر زیر). نام گذاری این رنگ‌ها هم به این دلیل هست که ترکیب همه این رنگ‌ها رنگ سیاه رو تولید می‌کنه و نبود هیچ یک، رنگ سفید (با فرض سفید بودن کاغذ :)). اگه به پرینتر‌ها دقت کرده باشین این ۴ رنگ اصلی جوهرها رو حتمن دیدین. چگونه یک جسم را رنگی می‌بینیم؟ [۴]در چاپ نیز مانند پیکسل‌های نمایشگر‌ها که بهشون اشاره شد تصاویر چاپ شده از یک سری نقاط (Spot) تشکیل شدند که می‌تونید توی تصویر زیر مشاهدشون کنین. به این فرآیند چاپ تصویر که بر اساس یک سری نقاط رنگی تصویر تشکیل می‌شه half-toning  میگن.نقاط CMYK یک تصویر پس از چاپ [۵] پس اگه طراحی قراره مثلا روی محیط وب کار بشه و با صفحات دیجیتالی دیده بشه باید مود رنگی اون RGB باشه ولی اگه قراره چاپ بشه باید مود رنگی اون CMYK‌ باشه. البته اوضاع به همین سادگی نیست. مشخصا همه رنگ‌هایی که تو سیستم رنگی RGB وجود داره توی CMYK وجود نداره. احتمالا زمان طراحی و انتخاب رنگ توی نرم افزارهای ادوبی شده که بعد انتخاب یک رنگی، در گوشه طیف رنگی، رنگ انتخاب شده رو توی یه مربع کوچیک که نشون میده، یه مثلث اخطار هم بغلش براتون ظاهر شده. این مثلث اشاره به همین موضوع داره و میگه که این رنگ رو اگه بخواین چاپ کنین اینیکه دارین می‌بینین نمیشه و اصطلاحا WISIWYG (یعنی What you see is what you get) نیست. برای اینکه رنگی که موقع چاپ به‌دست میاد رو ببینین دو بار روی اون مثلث کلیک کنین. البته برای این مشکل یه سری راه‌حل‌هایی ارائه شده که مثلا برای رفع اون میشه از رنگ‌های کمپانی پنتون استفاده کرد که تضمین می‌کنه رنگی که مشاهده می‌کنین بعد چاپ هم همین رنگ خواهد بود. RGB vs. CMYK vs. Visible Colors [۶]در ادامه جا داره یه این هم اشاره کنم که سیستم‌های دیگری هم برای رنگ‌ها به غیر از RGB و CMYK وجود داره که یکی از پرکاربردترین اون‌ها HSB یا (Hue, Saturation, Brightness) هست.لیست منابع و لینک‌ها:[۱] The surprising pattern behind color names around the world (+) [۲] Color Basics (+)[۳] Color Theory (+), (+)[۴] What is CMYK Color? (+)[۵] What’s the difference between RGB, CMYK and Spot (PMS) colors? (+)[۶] Designing for Print: RGB vs CMYK (+) و Some useful infographics (+), (+), and (+)</description>
                <category>اینترنردز</category>
                <author>محمدحسین ستاریان</author>
                <pubDate>Thu, 06 Jun 2019 03:56:32 +0430</pubDate>
            </item>
            </channel>
</rss>