Which Linux distro do you use?
Anonymous Poll
33%
Debian
8%
openSUSE
0%
CentOS
0%
Manjaro
0%
pop!_os
50%
Arch Linux
17%
Linux mint
42%
Ubuntu
42%
Kali Linux
0%
Rocky Linux
مرحله اول: تعریف ثابتها
در این قسمت سه مقدار ثابت تعریف شده است:
GITHUB_API آدرس اصلی API گیتهاب است.
CACHE_KEY کلیدی است که برای ذخیره اطلاعات در
CACHE_TTL_MS مدت اعتبار کش را مشخص میکند. مقدار
بنابراین اگر اطلاعات کمتر از ۳۰ دقیقه قبل دریافت شده باشند، برنامه دوباره به GitHub درخواست ارسال نمیکند.
مرحله دوم: ساختار دادههای کش
این Interface مشخص میکند که اطلاعات ذخیرهشده در مرورگر چه ساختاری دارند.
دو مقدار ذخیره میشود:
نمونه دادهای که در
مرحله سوم: خواندن کش
اولین کاری که برنامه انجام میدهد این است که بررسی کند آیا قبلاً اطلاعاتی ذخیره شده یا خیر.
اگر هیچ دادهای وجود نداشته باشد:
در غیر این صورت داده JSON به شیء جاوااسکریپت تبدیل میشود.
حالا باید بررسی شود که کش هنوز معتبر است یا نه.
در این خط:
اگر اختلاف این دو بیشتر از ۳۰ دقیقه باشد، کش منقضی شده است.
در نتیجه:
اما اگر کمتر از ۳۰ دقیقه گذشته باشد:
و دیگر هیچ درخواستی به GitHub ارسال نمیشود.
مرحله چهارم: ذخیره اطلاعات در کش
این تابع بعد از دریافت اطلاعات از GitHub اجرا میشود.
ابتدا یک شیء میسازد:
سپس آن را به رشته JSON تبدیل کرده و در
اگر مرورگر اجازه استفاده از Storage را ندهد، برنامه کرش نمیکند و فقط از این مرحله عبور میکند.
مرحله پنجم: دریافت اطلاعات از GitHub
اصلیترین قسمت برنامه این تابع است:
ابتدا کش بررسی میشود.
اگر اطلاعات داخل کش موجود باشد، همان دادهها برگردانده میشوند.
اما اگر کش وجود نداشته باشد، درخواست به GitHub ارسال میشود.
در این آدرس، مقدار
مثلاً:
GitHub لیست Repositoryهای عمومی این کاربر را برمیگرداند.
بررسی موفق بودن درخواست
بعد از دریافت پاسخ، ابتدا وضعیت آن بررسی میشود.
اگر پاسخ موفق نباشد (مانند 404 یا 403)، یک Error ساخته میشود.
در غیر این صورت اطلاعات JSON خوانده میشوند.
مرحله ششم: حذف Repositoryهای Fork
در GitHub ممکن است کاربر پروژههای دیگران را Fork کرده باشد.
اگر فقط پروژههای اصلی خود کاربر مورد نیاز باشند، از این کد استفاده میشود:
عبارت
مرحله هفتم: ذخیره نتیجه در کش
بعد از دریافت اطلاعات، آنها در مرورگر ذخیره میشوند.
در نتیجه اگر کاربر دوباره صفحه را باز کند، تا ۳۰ دقیقه اطلاعات از Storage خوانده میشوند و درخواست جدیدی ارسال نخواهد شد.
مرحله هشتم: مدیریت خطا
اگر اینترنت قطع باشد یا GitHub پاسخ ندهد، برنامه نباید متوقف شود.
به همین دلیل از
به جای کرش کردن، یک آرایه خالی برگردانده میشود تا رابط کاربری همچنان قابل نمایش باشد.
مرحله نهم: محاسبه آمار Repositoryها
تابع
روی Repositoryهای دریافتشده چند آمار تولید میکند.
۱- تعداد Repositoryها
فقط تعداد کل پروژهها را محاسبه میکند.
۲- مجموع ستارهها
const GITHUB_API = "https://api.github.com";
const CACHE_KEY = "v0id_gh_cache_v1";
const CACHE_TTL_MS = 1000 * 60 * 30;
در این قسمت سه مقدار ثابت تعریف شده است:
GITHUB_API آدرس اصلی API گیتهاب است.
CACHE_KEY کلیدی است که برای ذخیره اطلاعات در
sessionStorage استفاده میشود.CACHE_TTL_MS مدت اعتبار کش را مشخص میکند. مقدار
1000 * 60 * 30 یعنی ۳۰ دقیقه.بنابراین اگر اطلاعات کمتر از ۳۰ دقیقه قبل دریافت شده باشند، برنامه دوباره به GitHub درخواست ارسال نمیکند.
مرحله دوم: ساختار دادههای کش
interface CachePayload {
timestamp: number;
repos: GithubRepo[];
}این Interface مشخص میکند که اطلاعات ذخیرهشده در مرورگر چه ساختاری دارند.
دو مقدار ذخیره میشود:
timestamp زمان ذخیره شدن دادههاrepos لیست Repositoryهانمونه دادهای که در
sessionStorage ذخیره میشود:{
"timestamp": 1715000000000,
"repos": [...]
}مرحله سوم: خواندن کش
function readCache(): GithubRepo[] | null
اولین کاری که برنامه انجام میدهد این است که بررسی کند آیا قبلاً اطلاعاتی ذخیره شده یا خیر.
const raw = sessionStorage.getItem(CACHE_KEY);
اگر هیچ دادهای وجود نداشته باشد:
return null;
در غیر این صورت داده JSON به شیء جاوااسکریپت تبدیل میشود.
const parsed = JSON.parse(raw);
حالا باید بررسی شود که کش هنوز معتبر است یا نه.
if (Date.now() - parsed.timestamp > CACHE_TTL_MS)
در این خط:
Date.now() زمان فعلی را بر حسب میلیثانیه برمیگرداند.parsed.timestamp زمان ذخیره شدن اطلاعات است.اگر اختلاف این دو بیشتر از ۳۰ دقیقه باشد، کش منقضی شده است.
در نتیجه:
return null;
اما اگر کمتر از ۳۰ دقیقه گذشته باشد:
return parsed.repos;
و دیگر هیچ درخواستی به GitHub ارسال نمیشود.
مرحله چهارم: ذخیره اطلاعات در کش
function writeCache(repos: GithubRepo[])
این تابع بعد از دریافت اطلاعات از GitHub اجرا میشود.
ابتدا یک شیء میسازد:
const payload = {
timestamp: Date.now(),
repos
};سپس آن را به رشته JSON تبدیل کرده و در
sessionStorage ذخیره میکند.sessionStorage.setItem(
CACHE_KEY,
JSON.stringify(payload)
);
اگر مرورگر اجازه استفاده از Storage را ندهد، برنامه کرش نمیکند و فقط از این مرحله عبور میکند.
مرحله پنجم: دریافت اطلاعات از GitHub
اصلیترین قسمت برنامه این تابع است:
fetchGithubRepos(username)
ابتدا کش بررسی میشود.
const cached = readCache();
if (cached) {
return cached;
}
اگر اطلاعات داخل کش موجود باشد، همان دادهها برگردانده میشوند.
اما اگر کش وجود نداشته باشد، درخواست به GitHub ارسال میشود.
fetch(
`https://api.github.com/users/${username}/repos`
)
در این آدرس، مقدار
username جایگزین نام کاربر میشود.مثلاً:
https://api.github.com/users/octocat/repos
GitHub لیست Repositoryهای عمومی این کاربر را برمیگرداند.
بررسی موفق بودن درخواست
بعد از دریافت پاسخ، ابتدا وضعیت آن بررسی میشود.
if (!res.ok)
اگر پاسخ موفق نباشد (مانند 404 یا 403)، یک Error ساخته میشود.
در غیر این صورت اطلاعات JSON خوانده میشوند.
const data = await res.json();
مرحله ششم: حذف Repositoryهای Fork
در GitHub ممکن است کاربر پروژههای دیگران را Fork کرده باشد.
اگر فقط پروژههای اصلی خود کاربر مورد نیاز باشند، از این کد استفاده میشود:
const repos = data.filter((r) => !r.fork);
عبارت
!r.fork یعنی فقط Repositoryهایی انتخاب شوند که مقدار fork آنها false باشد.مرحله هفتم: ذخیره نتیجه در کش
بعد از دریافت اطلاعات، آنها در مرورگر ذخیره میشوند.
writeCache(repos);
در نتیجه اگر کاربر دوباره صفحه را باز کند، تا ۳۰ دقیقه اطلاعات از Storage خوانده میشوند و درخواست جدیدی ارسال نخواهد شد.
مرحله هشتم: مدیریت خطا
اگر اینترنت قطع باشد یا GitHub پاسخ ندهد، برنامه نباید متوقف شود.
به همین دلیل از
try...catch استفاده شده است.catch (err) {
console.warn(err);
return [];
}به جای کرش کردن، یک آرایه خالی برگردانده میشود تا رابط کاربری همچنان قابل نمایش باشد.
مرحله نهم: محاسبه آمار Repositoryها
تابع
computeGithubStats()
روی Repositoryهای دریافتشده چند آمار تولید میکند.
۱- تعداد Repositoryها
repoCount: repos.length
فقط تعداد کل پروژهها را محاسبه میکند.
۲- مجموع ستارهها
🎃3
const totalStars = repos.reduce(
(sum, repo) => sum + repo.stargazers_count,
0
);
متد
reduce روی تمام پروژهها حرکت میکند و تعداد ستارههای هر پروژه را با هم جمع میکند.فرض کنید سه پروژه داریم:
Repository
Stars
Portfolio
15
Chat App
8
Dashboard
12
خروجی برابر خواهد بود با:
35
۳- پیدا کردن زبانهای پرکاربرد
ابتدا یک
Map ساخته میشود.const languageCounts = new Map();
سپس تمام Repositoryها پیمایش میشوند.
for (const repo of repos)
اگر پروژه زبان برنامهنویسی نداشته باشد، از آن عبور میشود.
if (!repo.language) continue;
در غیر این صورت تعداد استفاده از آن زبان افزایش پیدا میکند.
مثلاً نتیجه Map ممکن است این باشد:
TypeScript → 7
JavaScript → 5
Python → 2
Go → 1
در نهایت این زبانها بر اساس تعداد مرتب شده و فقط شش مورد اول انتخاب میشوند.
خروجی نهایی
در پایان تابع این شیء را برمیگرداند:
{
repoCount: repos.length,
totalStars,
topLanguages
}نمونه خروجی:
{
repoCount: 18,
totalStars: 142,
topLanguages: [
"TypeScript",
"JavaScript",
"Python",
"Go",
"Rust",
"C#"
]
}👾3
می تونید سورس کد کل پروژه رو داخل گیت هاب من داشته باشید
https://github.com/V0IDNETWORK/V0IDNETWORK-portfolio-v2
https://github.com/V0IDNETWORK/V0IDNETWORK-portfolio-v2
GitHub
GitHub - V0IDNETWORK/V0IDNETWORK-portfolio-v2
Contribute to V0IDNETWORK/V0IDNETWORK-portfolio-v2 development by creating an account on GitHub.
🤗3
Forwarded from کاف
This media is not supported in your browser
VIEW IN TELEGRAM
لحظهای که صدها مرد برای یک زنِ استثنایی از جا بلند شدند…
تمام آن تشویقها فقط برای یک نام بود: ماری کوری.
زنی که عمرش را وقف علم کرد و مسیر تاریخ را تغییر داد.
NiNa @Kafiha
تمام آن تشویقها فقط برای یک نام بود: ماری کوری.
زنی که عمرش را وقف علم کرد و مسیر تاریخ را تغییر داد.
او با آزمایشهایش روی اورانیوم، مفهوم رادیواکتیویته را کشف کرد،
ویژگیهای رادیواکتیو توریوم را شناخت
و توانست رادیوم را از دل ماده جدا کند—کاری که جهان علم را وارد عصر تازهای کرد ⚛️🔥
ماری کوری نهتنها اولین زنی بود که نوبل گرفت،
بلکه اولین دانشمندی شد که این جایزه را دو بار دریافت کرد؛
یکی در فیزیک (۱۹۰۳) و دیگری در شیمی (۱۹۱۱).
او پایهگذار علم رادیولوژی و یکی از تأثیرگذارترین چهرههای تاریخ علم است.
مادام کوری ثابت کرد
نبوغ جنسیت نمیشناسد؛ فقط اراده، کنجکاوی و شجاعت میخواهد.
و او هر سه را داشت… به شکلی که جهان را مجبور کرد بایستد و برایش دست بزند 👏
NiNa @Kafiha
❤3
VOIDNETWORK
اینا چیه من میسازم😂
from textual.app import App, ComposeResult
from textual.containers import Horizontal, Vertical
from textual.widgets import (
Header,
Footer,
Button,
Static,
DataTable,
ProgressBar,
Input,
)
class MailSender(App):
CSS = """
Screen {
background: #0b1220;
color: white;
}
Header {
background: #2563eb;
color: white;
}
Footer {
background: #111827;
color: #9ca3af;
}
#sidebar {
width: 30;
background: #111827;
border: round #2563eb;
padding: 1;
}
#content {
background: #0f172a;
padding: 1 2;
}
Button {
width: 100%;
height: 3;
margin-bottom: 1;
background: #1e293b;
color: white;
border: round #334155;
}
Button:hover {
background: #2563eb;
color: white;
border: round #3b82f6;
}
Button:focus {
background: #3b82f6;
color: black;
text-style: bold;
}
Input {
margin-top: 1;
border: round #2563eb;
background: #111827;
color: white;
}
DataTable {
margin-top: 1;
height: 1fr;
border: round #334155;
}
ProgressBar {
margin-top: 1;
color: #22c55e;
}
#stats {
height: 10;
padding: 1;
border: round #8b5cf6;
background: #111827;
color: white;
}
"""
def compose(self) -> ComposeResult:
yield Header()
with Horizontal():
with Vertical(id="sidebar"):
yield Static("📧 Mail Sender Pro\n")
yield Button("📊 Dashboard")
yield Button("👥 Contacts")
yield Button("📝 Templates")
yield Button("📨 Campaigns")
yield Button("⚙️ SMTP")
yield Button("📄 Logs")
yield Button("❌ Exit", id="exit")
with Vertical(id="content"):
yield Static(
"""[b]Dashboard[/b]
Total Emails : 12450
Sent : 12120
Failed : 330
SMTP : Connected
""",
id="stats",
)
yield Input(
placeholder="Search email..."
)
table = DataTable()
table.add_columns("Email", "Status")
table.add_row("ali@gmail.com", "✅ Sent")
table.add_row("sara@gmail.com", "✅ Sent")
table.add_row("test@test.com", "❌ Failed")
table.add_row("info@company.com", "⏳ Sending")
yield table
progress = ProgressBar(total=100)
progress.advance(73)
yield progress
yield Footer()
def on_button_pressed(self, event: Button.Pressed):
if event.button.id == "exit":
self.exit()
if __name__ == "__main__":
MailSender().run()
🦄3
VOIDNETWORK
اینا چیه من میسازم😂
راستش کارفرما ازم خواسته بود یه سیستم برای مدیریت ارتباط با کاربران و کارمند هاشون توسعه بدم سیستمی که بتونن خیلی راحت و متمرکز برای همه کاربران، یک کاربر خاص، همه کارمند ها یا حتی فقط یک کارمند، پیامک یا ایمیل ارسال کنن نکته مهم این بود که ارسال پیام ها کاملاً هدفمند، قابل مدیریت و مقیاس پذیر باشه و مدیر سیستم بتونه بدون دردسر مخاطب ها رو انتخاب و کمپین های مختلف رو اجرا کنه
برای همین کل پروژه رو در دو نسخه مجزا پیاده سازی کردم نسخه اول یک پنل گرافیکی (GUI Panel) بود که تمرکزش روی تجربه کاربری سادگی مدیریت و دسترسی سریع به تمام امکانات بود از انتخاب گیرنده ها گرفته تا ارسال انبوه یا تکی پیام مدیریت قالبهای پیام و کنترل فرآیند ارسال
در کنار اون یک نسخه مبتنی بر CLI هم توسعه دادم که بیشتر برای سناریو های اتوماسیون اجرای اسکریپت ها استفاده روی سرور ها و ادغام با سایر سرویس ها طراحی شده بود. این نسخه با وجود رابط متنی،تمام قابلیت های اصلی پنل گرافیکی رو در اختیار قرار میداد و برای محیط هایی که نیاز به سرعت انعطاف و اجرای خودکار فرآیند ها وجود داشت، گزینه بسیار مناسبی بود.
برای همین کل پروژه رو در دو نسخه مجزا پیاده سازی کردم نسخه اول یک پنل گرافیکی (GUI Panel) بود که تمرکزش روی تجربه کاربری سادگی مدیریت و دسترسی سریع به تمام امکانات بود از انتخاب گیرنده ها گرفته تا ارسال انبوه یا تکی پیام مدیریت قالبهای پیام و کنترل فرآیند ارسال
در کنار اون یک نسخه مبتنی بر CLI هم توسعه دادم که بیشتر برای سناریو های اتوماسیون اجرای اسکریپت ها استفاده روی سرور ها و ادغام با سایر سرویس ها طراحی شده بود. این نسخه با وجود رابط متنی،تمام قابلیت های اصلی پنل گرافیکی رو در اختیار قرار میداد و برای محیط هایی که نیاز به سرعت انعطاف و اجرای خودکار فرآیند ها وجود داشت، گزینه بسیار مناسبی بود.
❤2👏1
VOID
Lady is here
رفتم که بخرمش
فروشنده گفت هزینه نصب ویندوز و آنتی ویروس بقیه برنامه های مورد نیاز میشه ۱ میلیون 😂
منم گفتم اوکیه ولی ویندوز نمیخوام
گفت پس چی؟ گفتم ارچ لینوکس بریز روش حتما هم KDE
بنده خدا هم گفت باشه
فردا زنگ زد گفت ویندوز ریختم
فروشنده گفت هزینه نصب ویندوز و آنتی ویروس بقیه برنامه های مورد نیاز میشه ۱ میلیون 😂
منم گفتم اوکیه ولی ویندوز نمیخوام
گفت پس چی؟ گفتم ارچ لینوکس بریز روش حتما هم KDE
بنده خدا هم گفت باشه
فردا زنگ زد گفت ویندوز ریختم
❤2🥰1
لطفا به پیوی مراجعه کنید
به فروش رسید
کم کم دارم به آخرین مراحل توسعه یکی از پروژه های مورد علاقهم می رسم پروژهای که واقعا با اشتیاق و دقت روش کار کردم.
VOIDADB
یک ابزار متن باز و کراس پلتفرم برای مدیریت و کنترل دستگاه های اندرویدی از طریق Wireless ADB با رابط گرافیکی مدرن، CLI قدرتمند و معماری ماژولار که هم بهعنوان یک اپلیکیشن و هم به عنوان یک کتابخانه Python قابل استفاده خواهد بود.
هنوز کار تموم نشده اما بیصبرانه منتظرم نسخه نهایی رو منتشر کنم و بازخورد جامعه متنباز رو ببینم.
VOIDADB
یک ابزار متن باز و کراس پلتفرم برای مدیریت و کنترل دستگاه های اندرویدی از طریق Wireless ADB با رابط گرافیکی مدرن، CLI قدرتمند و معماری ماژولار که هم بهعنوان یک اپلیکیشن و هم به عنوان یک کتابخانه Python قابل استفاده خواهد بود.
هنوز کار تموم نشده اما بیصبرانه منتظرم نسخه نهایی رو منتشر کنم و بازخورد جامعه متنباز رو ببینم.
🏆3
فقط خواستم قبل از امتحان فردا یه چیزی بگم...
این چند وقت برای خیلی هامون سخت گذشت اتفاقاتی افتاد که شاید تمرکز، انگیزه و حتی حال خوبمون رو گرفت اگه حس میکنید اون طور که باید درس نخوندید یا آمادگی کامل ندارید خودتون رو سرزنش نکنید.
امتحان مهمه اما نه به اندازهی سلامتی، آرامش و امیدی که باید برای ادامه راه داشته باشید یه برگه امتحان قرار نیست ارزش شما یا آینده تون رو مشخص کنه.
فردا فقط سعی کنید بهترین تلاشتون رو بکنید حتی اگه فکر میکنید کم بوده همون تلاش هم ارزشمنده.
و در آخر از صمیم قلب برای همتون آرزوی موفقیت دارم چه رفیقایی که همیشه کنارم بودن، چه اونایی که هیچوقت چشم دیدن مارو نداشتن امیدوارم همه مون از این روزهای سخت عبور کنیم و روزهای خیلی بهتری در انتظارمون باشه.
موفق باشید و امیدوارم فردا با لبخند از جلسه امتحان بیرون بیاید. 🤍
این چند وقت برای خیلی هامون سخت گذشت اتفاقاتی افتاد که شاید تمرکز، انگیزه و حتی حال خوبمون رو گرفت اگه حس میکنید اون طور که باید درس نخوندید یا آمادگی کامل ندارید خودتون رو سرزنش نکنید.
امتحان مهمه اما نه به اندازهی سلامتی، آرامش و امیدی که باید برای ادامه راه داشته باشید یه برگه امتحان قرار نیست ارزش شما یا آینده تون رو مشخص کنه.
فردا فقط سعی کنید بهترین تلاشتون رو بکنید حتی اگه فکر میکنید کم بوده همون تلاش هم ارزشمنده.
و در آخر از صمیم قلب برای همتون آرزوی موفقیت دارم چه رفیقایی که همیشه کنارم بودن، چه اونایی که هیچوقت چشم دیدن مارو نداشتن امیدوارم همه مون از این روزهای سخت عبور کنیم و روزهای خیلی بهتری در انتظارمون باشه.
موفق باشید و امیدوارم فردا با لبخند از جلسه امتحان بیرون بیاید. 🤍
💘3
VOIDNETWORK
کم کم دارم به آخرین مراحل توسعه یکی از پروژه های مورد علاقهم می رسم پروژهای که واقعا با اشتیاق و دقت روش کار کردم. VOIDADB یک ابزار متن باز و کراس پلتفرم برای مدیریت و کنترل دستگاه های اندرویدی از طریق Wireless ADB با رابط گرافیکی مدرن، CLI قدرتمند…
This media is not supported in your browser
VIEW IN TELEGRAM
یه review
❤1