مسعود بیگی
2.96K subscribers
1.66K photos
185 videos
139 files
1.41K links
کالای ما دانش است


تبلیغات نداریم
Download Telegram
Forwarded from tech-afternoon (Amin Mesbahi)
✍️مرور چند روش رایج صفحه‌بندی (Pagination) در API Design

وقتی با داده‌های بزرگ سر و کار داریم، نمایش اطلاعات به صورت صفحه‌بندی شده خیلی مهم‌تر از حالت عادیه که دریافت داده از سمت سرور بار قابل توجهی نداره (چه سمت واکشی داده، چه سمت ارسال به سمت کلاینت)

و این خیلی مهم می‌شه که روش استاندارد و یکسانی داشته باشیم تا یکی شماره صفحه و تعداد رو توی GET نگیره یکی توی POST تا بتونیم هم جلو بار اضافی به سرور رو بگیریم هم کاربری یا توسعه‌دهنده‌ای که با API سر و کار داره دیوانه نشه!

1️⃣ روش Offset & Limit (یا Page & Size)

GET /users?limit=10&offset=20

این روش ساده و سرراسته، و امکان دسترسی مستقیم به صفحه دلخواه رو فراهم می‌کنه. ولی وقتی دیتاست خیلی بزرگ شه، مستعد درخواست‌های عمدی یا سهوی کند کننده است! یا اگر داده‌ها مرتب تغییر کنن، شما یا یه چیزی از قلم می‌ندازی یا تا بری صفحه ۲، دیتای صفحه ۱ افتاده توی صفحه ۲! (نرخ بالای تغییرات) کوئری‌اش هم اینجوریه:
-- SQL Server:
SELECT * FROM users
ORDER BY id
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY;

-- PostgreSQL:
SELECT * FROM users
ORDER BY id
LIMIT 10 OFFSET 20;

-- MongoDB:
db.users.find()
.sort({ id: 1 })
.skip(20)
.limit(10);


2️⃣ روش Cursor-based Pagination
توی این روش به جای استفاده از offset، از یک نشانگر (cursor) استفاده می‌کنیم که به عنوان مرجع برای ادامه‌ی داده‌ها عمل می‌کنه. معمولاً این cursor می‌تونه آخرین مقدار یک فیلد کلیدی مثل id یا تاریخ ایجاد باشه.
GET /users?limit=10&cursor=eyJpZCI6IDIwMH0=

این روش کارایی بهتری توی داده‌های بزرگ داره، یکی از دلایلش اینه که نیازی سورت کردن داده و بعدش رد کردن تعدادی رکورد نداره! بلکه مستقیم (با کمک ایندکس البته) می‌ره سراغ رکورد مورد نظر و تامام. اگر داده‌ها مرتب تغییر کنن، باز کاربر مسیر خودش رو پیمایش می‌کنه و داده‌های تکراری نمی‌بینه یا داده‌هایی رو از دست نمی‌ده.
ولی: پیچیدگی پیاده‌سازیش بیشتره. صفحه ۵ الزامان برای همه و در همه زمان‌ها یک داده‌ رو نشون نمی‌ده.
برای مقیاس بزرگ این روش مناسب‌تره، اون بار تحمیلی سورت و skip توی مقیاس بزرگ کمرشکنه!

3️⃣روش Seek-pagination (Keyset Pagination)
روش seek-pagination یا keyset pagination به روش cursor-based شباهت داره، ولی به صورت صریح از شرایط WHERE استفاده می‌کنه تا رکوردهایی که بعد از آخرین مقدار دیده شده قرار دارن رو برگردونه.
GET /orders?limit=10&last_id=1000

در اینجا فرض می‌کنیم که last_id نشان‌دهنده‌ی آخرین id دیده شده در صفحه قبلی هست. سرور از شرط WHERE id > 1000 استفاده می‌کنه تا رکوردهای بعدی رو برگردونه.

بهره‌وری بالایی توی کوئری‌های حجیم داره چون از ایندکس‌ها و شرایط ساده استفاده می‌کنه توی کوئری‌سازی. مضاف بر اینکه اطلاعات به صورت پیوسته و بدون تداخل برگردونده میشن. ولی: اگر بخوای رکوردها رو براساس چند فیلد مرتب کنی، ممکنه نیاز به تغییراتی در کوئری داشته باشی و توی کوئری‌های چندشرطی پیچیدگی دارن.


4️⃣روش Time-Based Pagination
GET /events?since=2023-10-01&until=2023-10-08


5️⃣روش Hypermedia (HATEOAS) Links
Link: </items?cursor=def456>; rel="next", </items?cursor=abc123>; rel="prev"


6️⃣روش Metadata in Responses
{
"data": [...],
"pagination": {
"total": 1000,
"next_cursor": "def456",
"has_more": true
}
}


💬 اولندش بحث؟ نظر؟ تجربه؟ دُوُمَندش ۴ و ۵ و ۶ رو توضیح ندادم که الکی مثلا کنجکاوی ایجاد کنم، هزاران و میلیان‌ها ری‌اکشن ⚙️ بدید که توضیح بدم و بگم چرا روش HATEOAS روش منطبق با REST principles ذیل discoverability است!! 😅 سِوُمَندش دون بپاشم برای پرداختن عمیق‌تر به اهمیت ایندکس و درک ساختاریش، بعد از یخورده مطلب حول طراحی API نوشتم...

#API_Design
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Forwarded from tech-afternoon (Amin Mesbahi)
✍️2️⃣ توضیح روش‌های ۴ تا ۶ صفحه‌بندی (Pagination) در API

4️⃣ روش Time-Based Pagination
وقتی داده‌هامون به ترتیب زمان ثبت می‌شن (مثلاً رویدادهای یک سیستم لاگ یا خبرنامه‌های زنده)، می‌تونیم با استفاده از پارامترهایی مثل since و until بازه‌ی زمانی دلخواهمون رو مشخص کنیم.
مثال:

GET /events?since=2025-01-01&until=2025-01-10

اینجا API رو طوری طراحی می‌کنیم که همه‌ی رویدادهایی که بین اول تا دهم ژانویه اتفاق افتاده رو برگردونه.

وقتی داده‌ها به ترتیب زمان ثبت می‌شن، این روش خیلی منطقی و طبیعیه؛ و برای استفاده، فهم ساده‌ای داره؛ ولی اگه چند رویداد دقیقا در یک بازه زمانی یکسان ثبت بشن، ممکنه با ترتیب دقیق برگردونده نشه. همچنین اگر بازه‌ی زمانی خیلی گسترده باشه، ممکنه تعداد زیادی رکورد برگرده که می‌تونه روی پرفرمنس تاثیر منفی بذاره.

5️⃣ روش Hypermedia (HATEOAS) Links
روش HATEOAS (Hypermedia As The Engine Of Application State) یکی از اصول کلیدی REST هست. توی این روش، پاسخ‌های API شامل لینک‌هایی به صفحات بعدی یا قبلی هستند. این لینک‌ها معمولاً در هدر یا بدنه‌ی پاسخ قرار می‌گیرند و به کلاینت می‌گن «برای ادامه اینجا رو ببین» یا «صفحه قبلی اینجاست».
مثال:
Link: </items?cursor=def456>; rel="next", </items?cursor=abc123>; rel="prev"

توی این مثال، لینک‌های next و prev به کلاینت کمک می‌کنن بدون اینکه خودشون URL ها رو بسازن، به صفحات بعدی یا قبلی دسترسی پیدا کنن.

بزرگ‌ترین مزیتش علاوه بر استاندارد بودن، اینه که کلاینت‌ها نیازی به دونستن ساختار URL‌ها ندارن؛ API خودش مسیر بعدی رو بهشون میگه. در ضمن به راحتی می‌شه لینک‌های مختلف (مثلاً first، last، یا حتی لینک‌های مرتبط) رو اضافه کرد.از طرفی مدیریت و تولید این لینک‌ها به دقت نیاز داره تا همه‌ی روابط درست تعریف بشه؛ و استفاده از هدرهای HTTP اضافی ممکنه برای برخی کلاینت‌ها و ابزارها پیچیده باشه.


6️⃣ روش Metadata in Responses
توی این روش، به جای ارسال اطلاعات صفحه‌بندی در هدر، کل متادیتا (مثل تعداد کل رکوردها، cursor بعدی، و وضعیت وجود صفحه‌ی بعدی) رو توی بدنه‌ی پاسخ JSON می‌گنجونیم. این کار باعث می‌شه کلاینت به راحتی اطلاعات لازم رو از یک جا دریافت کنه.

{
"data": [...],
"pagination": {
"total": 1000,
"next_cursor": "def456",
"has_more": true
}
}

اینجا کلاینت علاوه بر داده‌های اصلی، اطلاعات کاملی از وضعیت صفحه‌بندی دریافت می‌کنه. خوبیش اینه که همه‌ی اطلاعات مورد نیاز برای صفحه‌بندی توی یک JSON مشخص هستن و خوانایی بالایی هم داره چون ساختار JSON معمولاً برای توسعه‌دهنده‌ها آشنا و راحته. ولی از اون سمت اضافه کردن متادیتا ممکنه حجم پاسخ رو کمی بیشتر کنه. همچنین با استانداردهای هدر HTTP در تضاده؛ یعنی برخی استانداردهای REST ترجیح می‌دن اطلاعات مربوط به ناوبری در هدر قرار بگیره، اگرچه این موضوع بیشتر یک نکته سبک‌سازیه تا یک مشکل جدی.

💬 نظر؟ بریم سراغ موضوع دیگه: 🤓
یا روی API Design ادامه بدیم: ⚙️

اگر روی API Design بمونیم:
- موضوع API Documentation و Discoverability
- استراتژی‌های مدیریت نسخه‌بندی API در طول زمان (API Evolution)
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
تو به jack S3 فکر میکنی و من به S3 Storage ، ما مثل هم نیستیم 😁
👎1
Forwarded from tech-afternoon (Amin Mesbahi)
رویکرد جدید تست نرم‌افزار با ACH

متا یک رویکرد جدید (از جنبه‌هایی جدید) نسبت به تولید خودکار تست‌های نرم‌افزار اتخاذ کرده با ابزاری به اسم ACH.

🌱 این ACH چیه؟
توی متا، ابزاری به اسم Automated Compliance Hardening (ACH) داریم که توی تست نرم‌افزار کلی تحول ایجاد کرده. این سیستم، از مدل‌های زبان بزرگ (LLM) استفاده می‌کنه تا به روش «mutation-guided» تست‌هایی تولید کنه. به عبارت دیگه، ACH با وارد کردن خطاهای عمدی (که بهشون «mutants» می‌گیم) توی کد، دنبال این می‌گرده که آیا تست‌های موجود اون خطاها رو پیدا می‌کنن یا نه. مثلا، توی حوزه حریم خصوصی، ACH به صورت خودکار به دنبال اشکالات مرتبط با حریم خصوصی می‌گرده و مطمئن می‌شه که این خطاها به سیستم‌های ما راه پیدا نکنن. نتیجه؟ کدهای ما محکم‌تر می‌شن و ریسک حریم خصوصی کمتر می‌شه.

همچنین ACH تست‌های واحد (unit tests) می‌سازه که هدفشون شکار اون خطاهای مشخصه. جالب‌تر اینکه، ما فقط نیاز داریم به صورت متنی و ساده توضیح بدیم که دنبال چه نوع خطاهایی هستیم؛ حتی اگه توضیحاتمون ناقص یا حتی یه کم متناقض باشه، ACH باز هم تست‌هایی تولید می‌کنه که تضمین می‌کنه اون خطاها رو پیدا می‌کنن.

در گذشته، بیشتر روش‌های تست اتوماتیک فقط روی افزایش پوشش کد متمرکز بودن، ولی افزایش پوشش کد همیشه تضمین نمی‌کنه که خطاها رو پیدا کنیم. ACH از این سنت فاصله می‌گیره و به‌طور خاص خطاها رو هدف قرار می‌ده، البته غالباً باعث افزایش پوشش هم می‌شه. یه نکته خوب اینه که ACH بر پایه اصول Assured LLM-based Software Engineering ساخته شده، به این معنا که تضمین داره تست‌های تولید شده واقعاً اون خطاها رو شکار می‌کنن.

❓چطوری کار می‌کنه؟
تکنیک‌های mutation testing مدتهاست که استفاده می‌شدن؛ یعنی با ایجاد خطاهای عمدی (mutants) توی کد (البته به نحوی که از تولید نهایی دور بمونن) می‌خوایم ببینیم که آیا تست‌ها این تغییرات رو می‌گیرن یا نه. مشکل این روش‌ها این بود که این mutants اغلب واقع‌گرایانه نبودن و کماکان نیاز به نوشتن دستی تست‌ها توسط انسان وجود داشت.

ACH با استفاده از قابلیت‌های مدل‌های زبان بزرگ (LLM) به دو مشکل اصلی پایان می‌ده:

- تولید mutants‌هایی که واقعاً نمایانگر خطاهای واقعی باشن.
- تولید خودکار تست‌ها برای شکار اون خطاها.

مراحل کار ACH:

۱: توضیح خطا: شما توضیح می‌دی که دنبال چه نوع خطاهایی هستی.

۲: تولید خطاها: ACH براساس توضیحات، تعداد زیادی خطا تولید می‌کنه.

۳: تولید تست‌ها: سپس این خطاها رو به عنوان ورودی می‌گیره و تست‌هایی می‌سازه که مطمئن بشیم اون خطاها رو پیدا می‌کنن.

👁 چرا مهمه؟
فکر کنید متا با اون همه برنامه‌نویس و سیستم‌های مختلف، چطور باید مطمئن بشه که همه چیز درست کار می‌کنه و مخصوصاً مسائل مربوط به حریم خصوصی کاربرها رعایت میشه؟ (منظور از حریم خصوصی همونه که شما راجع به یه کوفتی حرف می‌زنید، ۲ دقیقه بعدش اینستاگرام، پست و تبلیغ در مورد اون کوفت نمایش می‌ده 😁) اینجاست که ACH میاد به کمک!!:

- با استفاده از LLM‌ها، می‌تونه خیلی سریع و دقیق باگ تولید کنه
- تست‌های متناسب با اون باگ‌ها رو می‌نویسه
- تضمین می‌کنه که تست‌ها واقعاً اون باگ‌ها رو پیدا می‌کنن

🥸 کجا استفاده شده؟
متا این سیستم رو روی پلتفرم‌های مختلفش مثل:
- فیسبوک
- اینستاگرام 🤬
- واتس‌اپ
- مسنجر

تست کرده و نتایج خیلی خوبی گرفته.

🚀 آینده چی میشه؟
تیم متا می‌خواد این تکنولوژی رو گسترش بده و به جاهای بیشتری ببره. هدفشون اینه که:
- ارزیابی ریسک‌ها رو ساده‌تر کنن
- فشار ذهنی روی برنامه‌نویس‌ها رو کم کنن
- یه اکوسیستم امن‌تر برای همه بسازن

خلاصه اینکه ACH نشون میده چطور هوش مصنوعی می‌تونه به کمک برنامه‌نویس‌ها بیاد و کارهای سخت و وقت‌گیر رو براشون آسون‌تر کنه. مقاله هم روش دادن که می‌تونید عمیق‌تر مطالعه کنید...

به صورت کلی داستان تست نرم‌افزار داره تغییرات بزرگی می‌کنه. استارتاپ‌ها و شرکت‌های متعددی دارن روش کار می‌کنن. خصوصا الان که توضیح و توصیف عملکرد کدهای ساده و متوسط رو با درصد خوبی از پسش برمیان...

با اینکه ۲ تا موضوع توی همین کانال و کلا دنیای توسعه‌ نرم‌افزار فارسی زبان، خیلی نامحبوبه، یکی مستندسازی یکی تست، ولی اگر موافق باشین چند تا پست در موردش گپ بزنیم؟ (بزنیم: ⚙️ | نزنیم: 🤪، اگر نزنیم، شما بگید تا اگر بلد بودم بریم سراغش... 😉)
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
صبح شنبه تون بخیر #رابک نویسان 😁
🤣9👍2👏1
Forwarded from refhub
مهندسان عزیز روزتون مبارک
به مناسبت روز مهندس، یه کد تخفیف 30 درصدی براتون گذاشتیم
اولش با SOFTDAY شروع میشه، اما برای ادامه ش باید معمای زیر رو حل کنید :
یه برنامه‌نویس داره یه تابع رمزنگاری می‌نویسه. این تابع یه رشته می‌گیره و سه مرحله داره:

1- جمع مقدار ASCII همه‌ی کاراکترهای رشته رو حساب می‌کنه.
2- عدد به‌دست‌اومده رو در خودش ضرب می‌کنه (به توان ۲ می‌رسونه).
3- از نتیجه، یه عدد فیبوناچی پیدا می‌کنه که ازش بزرگ‌تر یا مساویشه، بعد اختلافشون رو حساب می‌کنه.

اگه ورودی تابع کلمه‌ی 'Debug' باشه، خروجی عددش چیه؟ این عدد، سه رقم آخر کد تخفیفت می‌شه!

با ❤️ رفهاب
https://RefHub.ir
❤3👍1
Forwarded from شیرازلاگ (Goudarz Jafari)
📌 نشست ۲۳۶، مشترک شیرازلاگ و فرانت‌چپتر

🔹موضوع: آشنایی با وب‌اسمبلی (WebAssembly)

🎤 ارائه‌دهنده: محمد میرشایی

📢 وب‌اسمبلی (WebAssembly) یکی از جذاب‌ترین تکنولوژی‌های مدرن برای اجرای کدهای کارآمد در مرورگر است! اما دقیقاً چطور کار می‌کند؟ چه کاربردهایی دارد؟ و چرا توسعه‌دهندگان به آن علاقه‌مند شده‌اند؟

🎙 در این نشست، با مبانی وب‌اسمبلی، مزایا، محدودیت‌ها و نحوه استفاده از آن در پروژه‌های واقعی آشنا می‌شویم.

✨ اگر می‌خواهید بدانید چگونه می‌توان از WebAssembly در کنار JavaScript، Rust و C++ استفاده کرد، این نشست را از دست ندهید!

🚀 جهت شرکت در جلسه، حداکثر تا ساعت ۱۳:۳۰ (دو ساعت قبل از شروع جلسه) مشخصات خود را از طریق این لینک برای ما ارسال کنید.

✨ برگزاری به صورت حضوری و رایگان ✨
📅 تاریخ: پنج‌شنبه ۹ اسفند ماه ۱۴۰۳
🕒 از ساعت ۱۵:۰۰ تا ۱۶:۳۰

🔹 مکان: شیراز، باغ‌جنت، مجموعه فرهنگی ایثار

🗺 Geo URI: 29.611544, 52.469188
📌 OSM: https://osm.org/go/zGYh_4_U~?m=

منتظرتان هستیم! 🎨✨

🐧 @ShirazLUG
🥕 @FrontChapter
❤3🔥1
امروز برای #فرانت_چپتر به شیراز میرم، استوری هاش رو اگر شیلترفکن یاری بده در اینستا باهات به اشتراک میگذارم
https://www.instagram.com/massoud.beygi/
❤6🔥3
همین الان زنگ بزنید، شاید فردا دیر باشه
💔24❤1
Forwarded from tech-afternoon (Amin Mesbahi)
⚠️ این یک تبلیغ نیست.
هدف این کانال چیزی جز بیشتر یاد گرفتنمون نیست، دلیل معرفی این فرصت شغلی هم دقیقن همینه که فکر می‌کنم فرصتی برای یاد گرفتن بیشتره...

اگر خودتون یا از دوستانتون کسی back-end کار با گرایش به 📱 است که API نویسی رو خوب بلده، دو تا از دوستان قدیمی و نزدیک من که سال‌ها تجربه کار توی شرکت‌هایی مثل ING, Nike و... در حوزه هوش‌مصنوعی و دیتاساینس دارن، برگشتن ایران و تلاش می‌کنن به دور از هیاهو سرویس‌ها و ابزارهای هوش‌مصنوعی درست‌وحسابی برای کسب‌وکارهای کوچیک توسعه بدن. لذا فرصت خوبی برای یادگیری و رشد فردی و کار خوب کردن محیا کردن.

📱🤝 اگر تمایل داشتید بیشتر بدونید یا به دوستانتون معرفی کنید این شرح شغلی‌شون است. اینم آدرس سایتشون است!
Please open Telegram to view this post
VIEW IN TELEGRAM
مسعود بیگی
به نظرتون حق با کدومه؟
جواب درست اینه که هرکدوم به نفع مملکت خودشون دارن تلاش میکنن، پس نمیتونیم بگیم حق واقعا با کیه؟ سیاست همینه. کشورها به جز چندتا انگشت شمار، همه به فکر منافع خودشونن فقط و این به نظرم درسته.
اصلا کشور یعنی چی؟ یه مرز که مردم درونش برای اهداف و پیشرفت مشترکشون تلاش میکنن.
🔥3👎1
Forwarded from InvestFund
Media is too big
VIEW IN TELEGRAM
❓بدترین سوال سرمایه‌گذار از استارتاپ: چقدر بازارت بزرگ هست؟

💡 سم آلتمن میگه، بدترین سوال راجع به بزرگ بودن بازار هست، خیلی از استارتاپ‌ها در ابتدا شاید در بازار بزرگی حضور نداشته باشن اما مهم میزان احتمال رشد اون بازار در آینده است، خیلی از استارتاپ‌ها آغازگر حرکتی هستند که یک بازار رو قراره رشد بده، اما بهترین سوال؟!
📌 چقدر از یک بازار کوچک رو استارتاپ می‌تونه تصاحب کنه؟! آلتمن اعتقاد داره بهترین استارتاپ‌ها بازار خیلی کوچک رو هدف قرار دادن ولی سهم بزرگی از اون رو گرفتن.

📍چند مثال از اشتباه بودن دنبال کردن بازار بزرگ برای استارتاپ:

🔸 زمانی که شاپیفای به دنبال جذب سرمایه بود، سرمایه‌گذارها به این علت که کلا 40 الی 50 هزار فروشگاه انلاین وجود داشت ریجکتش می‌کردند، در حالی که دلیل تعداد پایین فروشگاه آنلاین نبود راه‌حلی مثل شاپیفای بود.
🔸 یا برایان چسکی از مقایسه تعداد خونه‌های اجاره‌ای کوتاه مدت با اندازه بازار AirBNB در ابتدا می‌گفت در حالی که با وجود AirBNB صاحب خونه‌ها به فکر درامد از اجاره کوتاه مدت افتادند.
🔸 مثال اوبر و اسنپ هم همین بوده، بازار به واسطه یک راه‌حل خیلی بزرگ شده.

@Investingfund
👍4👎1
این یکی از اسلایدهای ارائه ی امسال فرانت چپتر بود و فکر میکنم شاید مهم ترین پیام هم همین بود.
در مواجهه با مشکلات و تعارضات تیمی و سازمانی ما به جای فرار باید بریم به سمت گفتگوی بالغانه و صادقانه و از همینجاست که بلوغ سازمان کم کم شکل می گیرد.
درس بسیار ارزشمند و سختی که متاسفانه من خیلی دیر گرفتم.
🔥18👍3
موافقید یه لیست از کانال های با ارزش و کمتر دیده شده رو به عنوان عیدی با هم منتشر کنیم ؟
👍39👎4
وقتی رترو داریم :))
🤣13🔥2👎1
گروه صنعتی انتخاب ۵۱ درصد از سهام «باسلام» را خرید
یک رانتی بزرگ، یک رانتی کوچک تر را خرید.
🤣20👎2👍1
Forwarded from iCodeNext
🎉 روز جهانی زن یک روز بزرگداشت جهانی است که هر ساله در ۸ مارس (۱۸ اسفند) برای بزرگداشت دستاوردهای فرهنگی، سیاسی و اجتماعی و اقتصادی زنان جشن گرفته می‌شود.

افرادی که در حوزه ی نرم افزار ( برنامه نویس، امنیت، شبکه، طراحان رابط کاربری و کلی حوزه ی دیگه) هم فعالیت دارند و در هر شرکتی تاثیر گذار هم هستند، کم نیستند. بنظرم متاسفانه وضعیت مناسبی برای برابری فرصت‌ها در این فعالیت‌ها برای زنان و دختران وجود ندارد، یا حداقل با شرایط ایده‌آل فاصله‌ی زیادی داریم.

همچنان در هر جای دنیا باز هم میبینیم که این عدم برابری وجود داره، حتی برای افرادی که واقعا متخصص هم هستند، باز این نابرابری در حقوق، در استخدام در پیشرفت شغلی به وضوح دیده میشه، و یه جورایی انگار همه ی ماها در این عدم برابری نقش داریم. امیدوارم روزی بتونیم این قضیه رو کامل حذف کنیمش.



❤️ روز جهانی زن بر تمام افرادی که در این کانال هستید مبارک.
❤13🤣2👍1