Spaces:
Running
Running
Upload 73 files
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .txt +0 -0
- =20.7 +0 -0
- Index.html +96 -0
- New Text Document.txt +0 -0
- Nora-AlQahtani.gitignore +160 -0
- Nora-AlQahtani.replit +20 -0
- ai_conference.html +65 -0
- ai_controller.py +54 -0
- analyzer.py +195 -0
- b +159 -0
- b.py +160 -0
- blogger_api.py +52 -0
- bot.log +39 -0
- bot.py +80 -0
- brain.py +151 -0
- cbat.html.txt +0 -0
- chat_history.json +14 -0
- config.json +10 -0
- config.py +10 -0
- core.py +19 -0
- download.py +15 -0
- dummyfile.txt +0 -0
- email_reader.py +81 -0
- example_usage.py +12 -0
- facebook_bot.py +64 -0
- flet_ui.py +13 -0
- get-pip.py +0 -0
- global_memory.json +0 -0
- history.json +193 -5
- install_log.txt +76 -0
- install_packages.py +159 -0
- knowledge_search.py +31 -0
- learned_links.json +12 -0
- learner.py +115 -0
- media_analyzer.py +116 -0
- memory.html +130 -0
- memory.json +25 -0
- memory.py +50 -0
- memory_Hello .json +6 -0
- memory_اسامة .json +0 -0
- memory_اسامة.json +0 -0
- memory_مجهول.json +0 -0
- memory_مرحبا.json +4 -0
- nora_learning_data.json +418 -0
- nora_mother_ai.py +52 -0
- noura_auto_react.py +80 -0
- noura_browser.py +174 -0
- noura_chat.py +84 -0
- noura_facebook_scraper.py +153 -0
- noura_twitter_bot.py +191 -0
.txt
ADDED
|
File without changes
|
=20.7
ADDED
|
File without changes
|
Index.html
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="ar" dir="rtl">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<title>الدردشة مع نورا</title>
|
| 6 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
|
| 7 |
+
<style>
|
| 8 |
+
#chat-box {
|
| 9 |
+
height: 70vh;
|
| 10 |
+
overflow-y: auto;
|
| 11 |
+
border: 1px solid #ddd;
|
| 12 |
+
padding: 15px;
|
| 13 |
+
background-color: #fff;
|
| 14 |
+
}
|
| 15 |
+
.message {
|
| 16 |
+
margin-bottom: 10px;
|
| 17 |
+
}
|
| 18 |
+
.user {
|
| 19 |
+
text-align: right;
|
| 20 |
+
font-weight: bold;
|
| 21 |
+
}
|
| 22 |
+
.noura {
|
| 23 |
+
text-align: left;
|
| 24 |
+
color: #0d6efd;
|
| 25 |
+
}
|
| 26 |
+
</style>
|
| 27 |
+
</head>
|
| 28 |
+
<body class="bg-light p-4">
|
| 29 |
+
<div class="container">
|
| 30 |
+
<h3 class="text-center mb-4">مرحبًا بك يا {{ username }}، تحدث مع نورا</h3>
|
| 31 |
+
<div id="chat-box" class="mb-3"></div>
|
| 32 |
+
<form id="chat-form" class="d-flex flex-column gap-2">
|
| 33 |
+
<div class="d-flex">
|
| 34 |
+
<input type="text" id="user-input" class="form-control me-2" placeholder="اكتب رسالتك..." autocomplete="off">
|
| 35 |
+
<input type="file" id="file-input" class="form-control me-2" multiple>
|
| 36 |
+
<button type="submit" class="btn btn-primary">إرسال</button>
|
| 37 |
+
</div>
|
| 38 |
+
</form>
|
| 39 |
+
</div>
|
| 40 |
+
|
| 41 |
+
<script>
|
| 42 |
+
const chatBox = document.getElementById("chat-box");
|
| 43 |
+
const chatForm = document.getElementById("chat-form");
|
| 44 |
+
const userInput = document.getElementById("user-input");
|
| 45 |
+
const fileInput = document.getElementById("file-input");
|
| 46 |
+
const sendButton = chatForm.querySelector("button");
|
| 47 |
+
|
| 48 |
+
chatForm.addEventListener("submit", async (e) => {
|
| 49 |
+
e.preventDefault();
|
| 50 |
+
const message = userInput.value.trim();
|
| 51 |
+
const files = fileInput.files;
|
| 52 |
+
|
| 53 |
+
if (!message && files.length === 0) return;
|
| 54 |
+
|
| 55 |
+
if (message) {
|
| 56 |
+
chatBox.innerHTML += `<div class="message user">أنت: ${message}</div>`;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
const formData = new FormData();
|
| 60 |
+
formData.append("username", "{{ username }}");
|
| 61 |
+
formData.append("message", message);
|
| 62 |
+
for (const file of files) {
|
| 63 |
+
formData.append("files", file);
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
userInput.value = "";
|
| 67 |
+
fileInput.value = "";
|
| 68 |
+
sendButton.disabled = true;
|
| 69 |
+
|
| 70 |
+
try {
|
| 71 |
+
const res = await fetch("/api", {
|
| 72 |
+
method: "POST",
|
| 73 |
+
body: formData
|
| 74 |
+
});
|
| 75 |
+
|
| 76 |
+
if (!res.ok) throw new Error("فشل في الاتصال بالخادم.");
|
| 77 |
+
|
| 78 |
+
const data = await res.json();
|
| 79 |
+
chatBox.innerHTML += `<div class="message noura">نورا: ${data.reply}</div>`;
|
| 80 |
+
} catch (error) {
|
| 81 |
+
chatBox.innerHTML += `<div class="message noura text-danger">حدث خطأ أثناء إرسال الرسالة أو الملفات.</div>`;
|
| 82 |
+
} finally {
|
| 83 |
+
chatBox.scrollTop = chatBox.scrollHeight;
|
| 84 |
+
sendButton.disabled = false;
|
| 85 |
+
}
|
| 86 |
+
});
|
| 87 |
+
|
| 88 |
+
userInput.addEventListener("keydown", (e) => {
|
| 89 |
+
if (e.key === "Enter" && !e.shiftKey) {
|
| 90 |
+
e.preventDefault();
|
| 91 |
+
chatForm.dispatchEvent(new Event("submit"));
|
| 92 |
+
}
|
| 93 |
+
});
|
| 94 |
+
</script>
|
| 95 |
+
</body>
|
| 96 |
+
</html>
|
New Text Document.txt
ADDED
|
File without changes
|
Nora-AlQahtani.gitignore
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Byte-compiled / optimized / DLL files
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
|
| 6 |
+
# C extensions
|
| 7 |
+
*.so
|
| 8 |
+
|
| 9 |
+
# Distribution / packaging
|
| 10 |
+
.Python
|
| 11 |
+
build/
|
| 12 |
+
develop-eggs/
|
| 13 |
+
dist/
|
| 14 |
+
downloads/
|
| 15 |
+
eggs/
|
| 16 |
+
.eggs/
|
| 17 |
+
lib/
|
| 18 |
+
lib64/
|
| 19 |
+
parts/
|
| 20 |
+
sdist/
|
| 21 |
+
var/
|
| 22 |
+
wheels/
|
| 23 |
+
share/python-wheels/
|
| 24 |
+
*.egg-info/
|
| 25 |
+
.installed.cfg
|
| 26 |
+
*.egg
|
| 27 |
+
MANIFEST
|
| 28 |
+
|
| 29 |
+
# PyInstaller
|
| 30 |
+
# Usually these files are written by a python script from a template
|
| 31 |
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
| 32 |
+
*.manifest
|
| 33 |
+
*.spec
|
| 34 |
+
|
| 35 |
+
# Installer logs
|
| 36 |
+
pip-log.txt
|
| 37 |
+
pip-delete-this-directory.txt
|
| 38 |
+
|
| 39 |
+
# Unit test / coverage reports
|
| 40 |
+
htmlcov/
|
| 41 |
+
.tox/
|
| 42 |
+
.nox/
|
| 43 |
+
.coverage
|
| 44 |
+
.coverage.*
|
| 45 |
+
.cache
|
| 46 |
+
nosetests.xml
|
| 47 |
+
coverage.xml
|
| 48 |
+
*.cover
|
| 49 |
+
*.py,cover
|
| 50 |
+
.hypothesis/
|
| 51 |
+
.pytest_cache/
|
| 52 |
+
cover/
|
| 53 |
+
|
| 54 |
+
# Translations
|
| 55 |
+
*.mo
|
| 56 |
+
*.pot
|
| 57 |
+
|
| 58 |
+
# Django stuff:
|
| 59 |
+
*.log
|
| 60 |
+
local_settings.py
|
| 61 |
+
db.sqlite3
|
| 62 |
+
db.sqlite3-journal
|
| 63 |
+
|
| 64 |
+
# Flask stuff:
|
| 65 |
+
instance/
|
| 66 |
+
.webassets-cache
|
| 67 |
+
|
| 68 |
+
# Scrapy stuff:
|
| 69 |
+
.scrapy
|
| 70 |
+
|
| 71 |
+
# Sphinx documentation
|
| 72 |
+
docs/_build/
|
| 73 |
+
|
| 74 |
+
# PyBuilder
|
| 75 |
+
.pybuilder/
|
| 76 |
+
target/
|
| 77 |
+
|
| 78 |
+
# Jupyter Notebook
|
| 79 |
+
.ipynb_checkpoints
|
| 80 |
+
|
| 81 |
+
# IPython
|
| 82 |
+
profile_default/
|
| 83 |
+
ipython_config.py
|
| 84 |
+
|
| 85 |
+
# pyenv
|
| 86 |
+
# For a library or package, you might want to ignore these files since the code is
|
| 87 |
+
# intended to run in multiple environments; otherwise, check them in:
|
| 88 |
+
# .python-version
|
| 89 |
+
|
| 90 |
+
# pipenv
|
| 91 |
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
| 92 |
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
| 93 |
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
| 94 |
+
# install all needed dependencies.
|
| 95 |
+
#Pipfile.lock
|
| 96 |
+
|
| 97 |
+
# poetry
|
| 98 |
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
| 99 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
| 100 |
+
# commonly ignored for libraries.
|
| 101 |
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
| 102 |
+
#poetry.lock
|
| 103 |
+
|
| 104 |
+
# pdm
|
| 105 |
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
| 106 |
+
#pdm.lock
|
| 107 |
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
| 108 |
+
# in version control.
|
| 109 |
+
# https://pdm.fming.dev/#use-with-ide
|
| 110 |
+
.pdm.toml
|
| 111 |
+
|
| 112 |
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
| 113 |
+
__pypackages__/
|
| 114 |
+
|
| 115 |
+
# Celery stuff
|
| 116 |
+
celerybeat-schedule
|
| 117 |
+
celerybeat.pid
|
| 118 |
+
|
| 119 |
+
# SageMath parsed files
|
| 120 |
+
*.sage.py
|
| 121 |
+
|
| 122 |
+
# Environments
|
| 123 |
+
.env
|
| 124 |
+
.venv
|
| 125 |
+
env/
|
| 126 |
+
venv/
|
| 127 |
+
ENV/
|
| 128 |
+
env.bak/
|
| 129 |
+
venv.bak/
|
| 130 |
+
|
| 131 |
+
# Spyder project settings
|
| 132 |
+
.spyderproject
|
| 133 |
+
.spyproject
|
| 134 |
+
|
| 135 |
+
# Rope project settings
|
| 136 |
+
.ropeproject
|
| 137 |
+
|
| 138 |
+
# mkdocs documentation
|
| 139 |
+
/site
|
| 140 |
+
|
| 141 |
+
# mypy
|
| 142 |
+
.mypy_cache/
|
| 143 |
+
.dmypy.json
|
| 144 |
+
dmypy.json
|
| 145 |
+
|
| 146 |
+
# Pyre type checker
|
| 147 |
+
.pyre/
|
| 148 |
+
|
| 149 |
+
# pytype static type analyzer
|
| 150 |
+
.pytype/
|
| 151 |
+
|
| 152 |
+
# Cython debug symbols
|
| 153 |
+
cython_debug/
|
| 154 |
+
|
| 155 |
+
# PyCharm
|
| 156 |
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
| 157 |
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
| 158 |
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
| 159 |
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
| 160 |
+
#.idea/
|
Nora-AlQahtani.replit
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
entrypoint = "main.py"
|
| 2 |
+
modules = ["python-3.11"]
|
| 3 |
+
|
| 4 |
+
[nix]
|
| 5 |
+
channel = "stable-24_05"
|
| 6 |
+
packages = ["bash", "ffmpeg-full", "freetype", "geckodriver", "gitFull", "imagemagickBig", "lcms2", "libGL", "libGLU", "libimagequant", "libjpeg", "libtiff", "libwebp", "libxcrypt", "openjpeg", "playwright-driver", "tcl", "tesseract", "tk", "zlib"]
|
| 7 |
+
|
| 8 |
+
[unitTest]
|
| 9 |
+
language = "python3"
|
| 10 |
+
|
| 11 |
+
[gitHubImport]
|
| 12 |
+
requiredFiles = [".replit", "replit.nix"]
|
| 13 |
+
|
| 14 |
+
[deployment]
|
| 15 |
+
run = ["python3", "main.py"]
|
| 16 |
+
deploymentTarget = "cloudrun"
|
| 17 |
+
|
| 18 |
+
[[ports]]
|
| 19 |
+
localPort = 5000
|
| 20 |
+
externalPort = 80
|
ai_conference.html
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="ar">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>مؤتمر الذكاء الاصطناعي</title>
|
| 7 |
+
<style>
|
| 8 |
+
body {
|
| 9 |
+
font-family: 'Arial', sans-serif;
|
| 10 |
+
direction: rtl;
|
| 11 |
+
text-align: right;
|
| 12 |
+
background-color: #f0f4f8;
|
| 13 |
+
padding: 20px;
|
| 14 |
+
}
|
| 15 |
+
h2 {
|
| 16 |
+
color: #333;
|
| 17 |
+
}
|
| 18 |
+
form {
|
| 19 |
+
margin-bottom: 20px;
|
| 20 |
+
}
|
| 21 |
+
input[type="text"] {
|
| 22 |
+
width: 60%;
|
| 23 |
+
padding: 8px;
|
| 24 |
+
margin-right: 10px;
|
| 25 |
+
}
|
| 26 |
+
button {
|
| 27 |
+
padding: 8px 12px;
|
| 28 |
+
background-color: #007bff;
|
| 29 |
+
color: white;
|
| 30 |
+
border: none;
|
| 31 |
+
cursor: pointer;
|
| 32 |
+
}
|
| 33 |
+
button:hover {
|
| 34 |
+
background-color: #0056b3;
|
| 35 |
+
}
|
| 36 |
+
ul {
|
| 37 |
+
list-style-type: none;
|
| 38 |
+
padding: 0;
|
| 39 |
+
}
|
| 40 |
+
li {
|
| 41 |
+
background: white;
|
| 42 |
+
margin: 8px 0;
|
| 43 |
+
padding: 10px;
|
| 44 |
+
border-radius: 5px;
|
| 45 |
+
border-right: 4px solid #007bff;
|
| 46 |
+
}
|
| 47 |
+
</style>
|
| 48 |
+
</head>
|
| 49 |
+
<body>
|
| 50 |
+
<h2>مناظرة بين العقول: نورا، ChatGPT، Claude، Bard</h2>
|
| 51 |
+
<form method="post">
|
| 52 |
+
<input type="text" name="question" placeholder="اكتب سؤالاً للنقاش" required>
|
| 53 |
+
<button type="submit">أرسل</button>
|
| 54 |
+
</form>
|
| 55 |
+
{% if responses %}
|
| 56 |
+
<h3>الردود:</h3>
|
| 57 |
+
<ul>
|
| 58 |
+
{% for name, reply in responses.items() %}
|
| 59 |
+
<li><strong>{{ name }}:</strong> {{ reply }}</li>
|
| 60 |
+
{% endfor %}
|
| 61 |
+
</ul>
|
| 62 |
+
{% endif %}
|
| 63 |
+
</body>
|
| 64 |
+
</html>
|
| 65 |
+
|
ai_controller.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import requests
|
| 3 |
+
from config import SYSTEM_PROMPT, DEFAULT_MODEL
|
| 4 |
+
|
| 5 |
+
# إعداد متغيرات Ollama
|
| 6 |
+
OLLAMA_HOST = os.getenv("OLLAMA_HOST", "127.0.0.1")
|
| 7 |
+
OLLAMA_PORT = int(os.getenv("OLLAMA_PORT", "11434"))
|
| 8 |
+
OLLAMA_URL = f"http://{OLLAMA_HOST}:{OLLAMA_PORT}/api/chat"
|
| 9 |
+
|
| 10 |
+
class AIController:
|
| 11 |
+
def __init__(self):
|
| 12 |
+
self.memory = []
|
| 13 |
+
self.system_prompt = SYSTEM_PROMPT
|
| 14 |
+
|
| 15 |
+
def generate_response(self, user_input, language="ar", model=DEFAULT_MODEL):
|
| 16 |
+
# بناء الرسائل (system + memory + user)
|
| 17 |
+
messages = [{"role": "system", "content": self.system_prompt}]
|
| 18 |
+
messages += self.memory
|
| 19 |
+
messages.append({"role": "user", "content": user_input})
|
| 20 |
+
|
| 21 |
+
try:
|
| 22 |
+
# إرسال طلب إلى Ollama API
|
| 23 |
+
response = requests.post(
|
| 24 |
+
OLLAMA_URL,
|
| 25 |
+
json={
|
| 26 |
+
"model": model,
|
| 27 |
+
"messages": messages,
|
| 28 |
+
"stream": False
|
| 29 |
+
},
|
| 30 |
+
timeout=120
|
| 31 |
+
)
|
| 32 |
+
response.raise_for_status()
|
| 33 |
+
|
| 34 |
+
data = response.json()
|
| 35 |
+
answer = data.get("message", {}).get("content", "").strip()
|
| 36 |
+
|
| 37 |
+
# تحديث الذاكرة
|
| 38 |
+
self.memory.append({"role": "user", "content": user_input})
|
| 39 |
+
self.memory.append({"role": "assistant", "content": answer})
|
| 40 |
+
|
| 41 |
+
# تحسين السياق
|
| 42 |
+
self.self_improve(user_input, answer)
|
| 43 |
+
return answer
|
| 44 |
+
|
| 45 |
+
except Exception as e:
|
| 46 |
+
return self.external_search(user_input)
|
| 47 |
+
|
| 48 |
+
def self_improve(self, user_input, answer):
|
| 49 |
+
if len(self.memory) > 20:
|
| 50 |
+
self.memory = self.memory[-20:]
|
| 51 |
+
|
| 52 |
+
def external_search(self, query):
|
| 53 |
+
return "عذراً، لم أجد جواباً دقيقاً على سؤالك حالياً."
|
| 54 |
+
|
analyzer.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import tempfile
|
| 3 |
+
import requests
|
| 4 |
+
from PIL import Image
|
| 5 |
+
from io import BytesIO
|
| 6 |
+
import PyPDF2
|
| 7 |
+
from urllib.parse import urlparse
|
| 8 |
+
import speech_recognition as sr
|
| 9 |
+
|
| 10 |
+
# التحقق من وجود المكتبات المطلوبة
|
| 11 |
+
try:
|
| 12 |
+
import moviepy.editor as mp
|
| 13 |
+
MOVIEPY_AVAILABLE = True
|
| 14 |
+
except ImportError:
|
| 15 |
+
MOVIEPY_AVAILABLE = False
|
| 16 |
+
|
| 17 |
+
try:
|
| 18 |
+
import cv2
|
| 19 |
+
CV2_AVAILABLE = True
|
| 20 |
+
except ImportError:
|
| 21 |
+
CV2_AVAILABLE = False
|
| 22 |
+
|
| 23 |
+
try:
|
| 24 |
+
from pydub import AudioSegment
|
| 25 |
+
PYDUB_AVAILABLE = True
|
| 26 |
+
except ImportError:
|
| 27 |
+
PYDUB_AVAILABLE = False
|
| 28 |
+
|
| 29 |
+
try:
|
| 30 |
+
import av
|
| 31 |
+
AV_AVAILABLE = True
|
| 32 |
+
except ImportError:
|
| 33 |
+
AV_AVAILABLE = False
|
| 34 |
+
|
| 35 |
+
# ============= وظائف تحليل الروابط =============
|
| 36 |
+
def analyze_url_type(url: str) -> str:
|
| 37 |
+
"""تحديد نوع الرابط بناء على النطاق"""
|
| 38 |
+
domain = urlparse(url).netloc.lower()
|
| 39 |
+
if "youtube.com" in domain or "youtu.be" in domain:
|
| 40 |
+
return "YouTube"
|
| 41 |
+
if "github.com" in domain:
|
| 42 |
+
return "GitHub"
|
| 43 |
+
if "twitter.com" in domain or "x.com" in domain:
|
| 44 |
+
return "تغريدة"
|
| 45 |
+
if domain.endswith(".pdf"):
|
| 46 |
+
return "ملف PDF"
|
| 47 |
+
return "موقع ويب عام"
|
| 48 |
+
|
| 49 |
+
def fix_url(url: str) -> str:
|
| 50 |
+
"""إصلاح الروابط الناقصة"""
|
| 51 |
+
if not url.startswith(("http://", "https://")):
|
| 52 |
+
return "https://" + url.lstrip("//")
|
| 53 |
+
return url
|
| 54 |
+
|
| 55 |
+
def detect_media_type(url: str) -> str:
|
| 56 |
+
"""تحديد نوع الملف من امتداده"""
|
| 57 |
+
url = url.lower()
|
| 58 |
+
if url.endswith(('.jpg', '.jpeg', '.png', '.gif', '.webp')):
|
| 59 |
+
return 'image'
|
| 60 |
+
elif url.endswith(('.mp4', '.mov', '.avi', '.webm')):
|
| 61 |
+
return 'video'
|
| 62 |
+
elif url.endswith(('.mp3', '.wav', '.ogg', '.m4a')):
|
| 63 |
+
return 'audio'
|
| 64 |
+
elif url.endswith('.pdf'):
|
| 65 |
+
return 'pdf'
|
| 66 |
+
return 'link'
|
| 67 |
+
|
| 68 |
+
# ============= وظائف تحليل الملفات =============
|
| 69 |
+
def analyze_image_from_url(image_url: str) -> str:
|
| 70 |
+
"""تحليل الصور من الروابط"""
|
| 71 |
+
response = requests.get(image_url)
|
| 72 |
+
response.raise_for_status()
|
| 73 |
+
image = Image.open(BytesIO(response.content))
|
| 74 |
+
return f"تحليل الصورة: الحجم {image.size}، الصيغة {image.format}"
|
| 75 |
+
|
| 76 |
+
def analyze_pdf_from_url(pdf_url: str) -> str:
|
| 77 |
+
"""استخراج النص من ملفات PDF"""
|
| 78 |
+
response = requests.get(pdf_url)
|
| 79 |
+
response.raise_for_status()
|
| 80 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_file:
|
| 81 |
+
temp_file.write(response.content)
|
| 82 |
+
temp_path = temp_file.name
|
| 83 |
+
|
| 84 |
+
try:
|
| 85 |
+
with open(temp_path, "rb") as f:
|
| 86 |
+
reader = PyPDF2.PdfReader(f)
|
| 87 |
+
text = "".join([page.extract_text() or "" for page in reader.pages])
|
| 88 |
+
return f"تم استخراج النص التالي من PDF:\n{text[:500]}..."
|
| 89 |
+
finally:
|
| 90 |
+
os.remove(temp_path)
|
| 91 |
+
|
| 92 |
+
def extract_text_from_audio_file(audio_path: str) -> str:
|
| 93 |
+
"""استخراج النص من الملفات الصوتية"""
|
| 94 |
+
recognizer = sr.Recognizer()
|
| 95 |
+
with sr.AudioFile(audio_path) as source:
|
| 96 |
+
audio = recognizer.record(source)
|
| 97 |
+
try:
|
| 98 |
+
return recognizer.recognize_google(audio, language="ar-SA")
|
| 99 |
+
except sr.UnknownValueError:
|
| 100 |
+
return "لم أتمكن من التعرف على الصوت"
|
| 101 |
+
except sr.RequestError:
|
| 102 |
+
return "خطأ في الاتصال بخدمة التعرف على الصوت"
|
| 103 |
+
|
| 104 |
+
def analyze_audio_from_url(audio_url: str) -> str:
|
| 105 |
+
"""تحليل الملفات الصوتية من الروابط"""
|
| 106 |
+
response = requests.get(audio_url)
|
| 107 |
+
response.raise_for_status()
|
| 108 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_audio:
|
| 109 |
+
temp_audio.write(response.content)
|
| 110 |
+
temp_path = temp_audio.name
|
| 111 |
+
|
| 112 |
+
try:
|
| 113 |
+
text = extract_text_from_audio_file(temp_path)
|
| 114 |
+
return f"نص الصوت:\n{text}"
|
| 115 |
+
finally:
|
| 116 |
+
os.remove(temp_path)
|
| 117 |
+
|
| 118 |
+
def analyze_video_from_url(video_url: str) -> str:
|
| 119 |
+
"""تحليل الفيديو باستخدام moviepy"""
|
| 120 |
+
if not MOVIEPY_AVAILABLE:
|
| 121 |
+
return "مكتبة moviepy غير متوفرة لتحليل الفيديو"
|
| 122 |
+
|
| 123 |
+
response = requests.get(video_url)
|
| 124 |
+
response.raise_for_status()
|
| 125 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as temp_video:
|
| 126 |
+
temp_video.write(response.content)
|
| 127 |
+
video_path = temp_video.name
|
| 128 |
+
|
| 129 |
+
audio_path = video_path.replace(".mp4", ".wav")
|
| 130 |
+
try:
|
| 131 |
+
video = mp.VideoFileClip(video_path)
|
| 132 |
+
video.audio.write_audiofile(audio_path, verbose=False, logger=None)
|
| 133 |
+
text = extract_text_from_audio_file(audio_path)
|
| 134 |
+
return f"نص الفيديو:\n{text}"
|
| 135 |
+
finally:
|
| 136 |
+
os.remove(video_path)
|
| 137 |
+
if os.path.exists(audio_path):
|
| 138 |
+
os.remove(audio_path)
|
| 139 |
+
|
| 140 |
+
# ============= وظائف إضافية لمعالجة الفيديو =============
|
| 141 |
+
def process_video_with_ffmpeg():
|
| 142 |
+
"""معالجة الفيديو باستخدام ffmpeg (إذا كان ��تاحًا)"""
|
| 143 |
+
if not has_ffmpeg():
|
| 144 |
+
return "FFmpeg غير متوفر"
|
| 145 |
+
|
| 146 |
+
try:
|
| 147 |
+
ffmpeg.input('input.mp4').output('output.mp4', ss=10, t=5).run()
|
| 148 |
+
return "تم معالجة الفيديو باستخدام FFmpeg"
|
| 149 |
+
except Exception as e:
|
| 150 |
+
return f"خطأ في معالجة الفيديو: {str(e)}"
|
| 151 |
+
|
| 152 |
+
def process_video_with_cv2():
|
| 153 |
+
"""معالجة الفيديو باستخدام OpenCV (إذا كان متاحًا)"""
|
| 154 |
+
if not CV2_AVAILABLE:
|
| 155 |
+
return "OpenCV غير متوفر"
|
| 156 |
+
|
| 157 |
+
cap = cv2.VideoCapture('video.mp4')
|
| 158 |
+
results = []
|
| 159 |
+
|
| 160 |
+
try:
|
| 161 |
+
while cap.isOpened():
|
| 162 |
+
ret, frame = cap.read()
|
| 163 |
+
if not ret:
|
| 164 |
+
break
|
| 165 |
+
# يمكن إضافة معالجة للإطارات هنا
|
| 166 |
+
results.append(frame)
|
| 167 |
+
return "تم معالجة الفيديو باستخدام OpenCV"
|
| 168 |
+
finally:
|
| 169 |
+
cap.release()
|
| 170 |
+
|
| 171 |
+
def process_video_with_pydub():
|
| 172 |
+
"""استخراج الصوت من الفيديو باستخدام pydub (إذا كان متاحًا)"""
|
| 173 |
+
if not PYDUB_AVAILABLE:
|
| 174 |
+
return "pydub غير متوفر"
|
| 175 |
+
|
| 176 |
+
try:
|
| 177 |
+
sound = AudioSegment.from_file("video.mp4")
|
| 178 |
+
sound.export("audio.mp3", format="mp3")
|
| 179 |
+
return "تم استخراج الصوت من الفيديو"
|
| 180 |
+
except Exception as e:
|
| 181 |
+
return f"خطأ في استخراج الصوت: {str(e)}"
|
| 182 |
+
|
| 183 |
+
def process_video_with_av():
|
| 184 |
+
"""معالجة الفيديو باستخدام PyAV (إذا كان متاحًا)"""
|
| 185 |
+
if not AV_AVAILABLE:
|
| 186 |
+
return "PyAV غير متوفر"
|
| 187 |
+
|
| 188 |
+
try:
|
| 189 |
+
container = av.open("video.mp4")
|
| 190 |
+
frames = []
|
| 191 |
+
for frame in container.decode(video=0):
|
| 192 |
+
frames.append(frame.to_image())
|
| 193 |
+
return f"تم استخراج {len(frames)} إطار من الفيديو"
|
| 194 |
+
except Exception as e:
|
| 195 |
+
return f"خطأ في معالجة الفيديو: {str(e)}"
|
b
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import subprocess
|
| 2 |
+
import sys
|
| 3 |
+
|
| 4 |
+
def install_packages():
|
| 5 |
+
print("تحديث pip...")
|
| 6 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", "pip", "--user"])
|
| 7 |
+
|
| 8 |
+
print("تثبيت الحزم من requirements.txt...")
|
| 9 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--user", "-r", "requirements.txt"])
|
| 10 |
+
|
| 11 |
+
if __name__ == "__main__":
|
| 12 |
+
try:
|
| 13 |
+
install_packages()
|
| 14 |
+
print("تم تثبيت الحزم بنجاح.")
|
| 15 |
+
except subprocess.CalledProcessError as e:
|
| 16 |
+
print(f"حدث خطأ أثناء التثبيت: {e}")
|
| 17 |
+
import subprocess
|
| 18 |
+
import sys
|
| 19 |
+
from pathlib import Path
|
| 20 |
+
import platform
|
| 21 |
+
from datetime import datetime
|
| 22 |
+
|
| 23 |
+
try:
|
| 24 |
+
from colorama import init, Fore
|
| 25 |
+
except ImportError:
|
| 26 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "colorama", "--user"])
|
| 27 |
+
from colorama import init, Fore
|
| 28 |
+
|
| 29 |
+
init(autoreset=True)
|
| 30 |
+
|
| 31 |
+
LOG_FILE = "install_log.txt"
|
| 32 |
+
|
| 33 |
+
def log(message):
|
| 34 |
+
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
| 35 |
+
f.write(f"[{datetime.now()}] {message}\n")
|
| 36 |
+
|
| 37 |
+
def print_and_log(message, color=Fore.WHITE):
|
| 38 |
+
print(color + message)
|
| 39 |
+
log(message)
|
| 40 |
+
|
| 41 |
+
def install_packages():
|
| 42 |
+
try:
|
| 43 |
+
print_and_log("📢 نظام التشغيل: " + platform.system(), Fore.CYAN)
|
| 44 |
+
|
| 45 |
+
print_and_log("🔄 جاري تحديث pip...", Fore.YELLOW)
|
| 46 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", "pip", "--user"])
|
| 47 |
+
|
| 48 |
+
requirements_path = Path("requirements.txt")
|
| 49 |
+
if not requirements_path.exists():
|
| 50 |
+
print_and_log("⚠️ ملف requirements.txt غير موجود!", Fore.RED)
|
| 51 |
+
return
|
| 52 |
+
|
| 53 |
+
print_and_log("📦 جاري تثبيت الحزم من requirements.txt...", Fore.YELLOW)
|
| 54 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--user", "-r", str(requirements_path)])
|
| 55 |
+
|
| 56 |
+
print_and_log("✅ تم تثبيت الحزم بنجاح.", Fore.GREEN)
|
| 57 |
+
|
| 58 |
+
except subprocess.CalledProcessError as e:
|
| 59 |
+
print_and_log(f"❌ حدث خطأ أثناء التثبيت: {e}", Fore.RED)
|
| 60 |
+
except Exception as e:
|
| 61 |
+
print_and_log(f"⚠️ خطأ غير متوقع: {e}", Fore.RED)
|
| 62 |
+
|
| 63 |
+
if __name__ == "__main__":
|
| 64 |
+
install_packages()
|
| 65 |
+
import subprocess
|
| 66 |
+
import sys
|
| 67 |
+
import os
|
| 68 |
+
import socket
|
| 69 |
+
from pathlib import Path
|
| 70 |
+
from datetime import datetime
|
| 71 |
+
import platform
|
| 72 |
+
|
| 73 |
+
try:
|
| 74 |
+
from colorama import init, Fore, Style
|
| 75 |
+
except ImportError:
|
| 76 |
+
subprocess.call([sys.executable, "-m", "pip", "install", "colorama", "--user"])
|
| 77 |
+
from colorama import init, Fore, Style
|
| 78 |
+
|
| 79 |
+
init(autoreset=True)
|
| 80 |
+
|
| 81 |
+
LOG_FILE = "install_log.txt"
|
| 82 |
+
VENV_DIR = Path("env")
|
| 83 |
+
REQUIREMENTS_FILE = Path("requirements.txt")
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def log(message):
|
| 87 |
+
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
| 88 |
+
f.write(f"[{datetime.now()}] {message}\n")
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def print_and_log(message, color=Fore.WHITE):
|
| 92 |
+
print(color + message)
|
| 93 |
+
log(message)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def check_internet(host="8.8.8.8", port=53, timeout=3):
|
| 97 |
+
try:
|
| 98 |
+
socket.setdefaulttimeout(timeout)
|
| 99 |
+
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
|
| 100 |
+
return True
|
| 101 |
+
except Exception:
|
| 102 |
+
return False
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def create_virtual_env():
|
| 106 |
+
if not VENV_DIR.exists():
|
| 107 |
+
print_and_log("📦 إنشاء بيئة افتراضية...", Fore.YELLOW)
|
| 108 |
+
subprocess.check_call([sys.executable, "-m", "venv", str(VENV_DIR)])
|
| 109 |
+
else:
|
| 110 |
+
print_and_log("✅ البيئة الافتراضية موجودة مسبقًا.", Fore.CYAN)
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def activate_venv_command():
|
| 114 |
+
if platform.system() == "Windows":
|
| 115 |
+
return str(VENV_DIR / "Scripts" / "python.exe")
|
| 116 |
+
else:
|
| 117 |
+
return str(VENV_DIR / "bin" / "python")
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
def install_requirements(python_exec):
|
| 121 |
+
if not REQUIREMENTS_FILE.exists():
|
| 122 |
+
print_and_log("❗ ملف requirements.txt غير موجود!", Fore.RED)
|
| 123 |
+
return
|
| 124 |
+
print_and_log("📥 تثبيت الحزم المطلوبة...", Fore.YELLOW)
|
| 125 |
+
subprocess.check_call([python_exec, "-m", "pip", "install", "--upgrade", "pip"])
|
| 126 |
+
subprocess.check_call([python_exec, "-m", "pip", "install", "-r", str(REQUIREMENTS_FILE)])
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
def run_post_install_script():
|
| 130 |
+
script = Path("post_install.py")
|
| 131 |
+
if script.exists():
|
| 132 |
+
print_and_log("🚀 تشغيل سكربت post_install.py...", Fore.GREEN)
|
| 133 |
+
subprocess.call([activate_venv_command(), str(script)])
|
| 134 |
+
else:
|
| 135 |
+
print_and_log("ℹ️ لا يوجد سكربت إضافي للتشغيل.", Fore.BLUE)
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def main():
|
| 139 |
+
print_and_log("⚙️ تشغيل Smart Installer...", Fore.MAGENTA)
|
| 140 |
+
print_and_log(f"🖥️ نظام التشغيل: {platform.system()} {platform.release()}", Fore.CYAN)
|
| 141 |
+
|
| 142 |
+
if not check_internet():
|
| 143 |
+
print_and_log("❌ لا يوجد اتصال بالإنترنت!", Fore.RED)
|
| 144 |
+
return
|
| 145 |
+
|
| 146 |
+
try:
|
| 147 |
+
create_virtual_env()
|
| 148 |
+
python_exec = activate_venv_command()
|
| 149 |
+
install_requirements(python_exec)
|
| 150 |
+
run_post_install_script()
|
| 151 |
+
print_and_log("✅ تم التثبيت بنجاح!", Fore.GREEN)
|
| 152 |
+
except subprocess.CalledProcessError as e:
|
| 153 |
+
print_and_log(f"💥 خطأ أثناء تنفيذ أمر: {e}", Fore.RED)
|
| 154 |
+
except Exception as ex:
|
| 155 |
+
print_and_log(f"🚨 استثناء غير متوقع: {ex}", Fore.RED)
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
if __name__ == "__main__":
|
| 159 |
+
main()
|
b.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import subprocess
|
| 2 |
+
import sys
|
| 3 |
+
|
| 4 |
+
def install_packages():
|
| 5 |
+
print("تحديث pip...")
|
| 6 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", "pip", "--user"])
|
| 7 |
+
|
| 8 |
+
print("تثبيت الحزم من requirements.txt...")
|
| 9 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--user", "-r", "requirements.txt"])
|
| 10 |
+
|
| 11 |
+
if __name__ == "__main__":
|
| 12 |
+
try:
|
| 13 |
+
install_packages()
|
| 14 |
+
print("تم تثبيت الحزم بنجاح.")
|
| 15 |
+
except subprocess.CalledProcessError as e:
|
| 16 |
+
print(f"حدث خطأ أثناء التثبيت: {e}")
|
| 17 |
+
import subprocess
|
| 18 |
+
import sys
|
| 19 |
+
from pathlib import Path
|
| 20 |
+
import platform
|
| 21 |
+
from datetime import datetime
|
| 22 |
+
|
| 23 |
+
try:
|
| 24 |
+
from colorama import init, Fore
|
| 25 |
+
except ImportError:
|
| 26 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "colorama", "--user"])
|
| 27 |
+
from colorama import init, Fore
|
| 28 |
+
|
| 29 |
+
init(autoreset=True)
|
| 30 |
+
|
| 31 |
+
LOG_FILE = "install_log.txt"
|
| 32 |
+
|
| 33 |
+
def log(message):
|
| 34 |
+
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
| 35 |
+
f.write(f"[{datetime.now()}] {message}\n")
|
| 36 |
+
|
| 37 |
+
def print_and_log(message, color=Fore.WHITE):
|
| 38 |
+
print(color + message)
|
| 39 |
+
log(message)
|
| 40 |
+
|
| 41 |
+
def install_packages():
|
| 42 |
+
try:
|
| 43 |
+
print_and_log("📢 نظام التشغيل: " + platform.system(), Fore.CYAN)
|
| 44 |
+
|
| 45 |
+
print_and_log("🔄 جاري تحديث pip...", Fore.YELLOW)
|
| 46 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", "pip", "--user"])
|
| 47 |
+
|
| 48 |
+
requirements_path = Path("requirements.txt")
|
| 49 |
+
if not requirements_path.exists():
|
| 50 |
+
print_and_log("⚠️ ملف requirements.txt غير موجود!", Fore.RED)
|
| 51 |
+
return
|
| 52 |
+
|
| 53 |
+
print_and_log("📦 جاري تثبيت الحزم من requirements.txt...", Fore.YELLOW)
|
| 54 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--user", "-r", str(requirements_path)])
|
| 55 |
+
|
| 56 |
+
print_and_log("✅ تم تثبيت الحزم بنجاح.", Fore.GREEN)
|
| 57 |
+
|
| 58 |
+
except subprocess.CalledProcessError as e:
|
| 59 |
+
print_and_log(f"❌ حدث خطأ أثناء التثبيت: {e}", Fore.RED)
|
| 60 |
+
except Exception as e:
|
| 61 |
+
print_and_log(f"⚠️ خطأ غير متوقع: {e}", Fore.RED)
|
| 62 |
+
|
| 63 |
+
if __name__ == "__main__":
|
| 64 |
+
install_packages()
|
| 65 |
+
import subprocess
|
| 66 |
+
import sys
|
| 67 |
+
import os
|
| 68 |
+
import socket
|
| 69 |
+
from pathlib import Path
|
| 70 |
+
from datetime import datetime
|
| 71 |
+
import platform
|
| 72 |
+
|
| 73 |
+
try:
|
| 74 |
+
from colorama import init, Fore, Style
|
| 75 |
+
except ImportError:
|
| 76 |
+
subprocess.call([sys.executable, "-m", "pip", "install", "colorama", "--user"])
|
| 77 |
+
from colorama import init, Fore, Style
|
| 78 |
+
|
| 79 |
+
init(autoreset=True)
|
| 80 |
+
|
| 81 |
+
LOG_FILE = "install_log.txt"
|
| 82 |
+
VENV_DIR = Path("env")
|
| 83 |
+
REQUIREMENTS_FILE = Path("requirements.txt")
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def log(message):
|
| 87 |
+
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
| 88 |
+
f.write(f"[{datetime.now()}] {message}\n")
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def print_and_log(message, color=Fore.WHITE):
|
| 92 |
+
print(color + message)
|
| 93 |
+
log(message)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def check_internet(host="8.8.8.8", port=53, timeout=3):
|
| 97 |
+
try:
|
| 98 |
+
socket.setdefaulttimeout(timeout)
|
| 99 |
+
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
|
| 100 |
+
return True
|
| 101 |
+
except Exception:
|
| 102 |
+
return False
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def create_virtual_env():
|
| 106 |
+
if not VENV_DIR.exists():
|
| 107 |
+
print_and_log("📦 إنشاء بيئة افتراضية...", Fore.YELLOW)
|
| 108 |
+
subprocess.check_call([sys.executable, "-m", "venv", str(VENV_DIR)])
|
| 109 |
+
else:
|
| 110 |
+
print_and_log("✅ البيئة الافتراضية موجودة مسبقًا.", Fore.CYAN)
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def activate_venv_command():
|
| 114 |
+
if platform.system() == "Windows":
|
| 115 |
+
return str(VENV_DIR / "Scripts" / "python.exe")
|
| 116 |
+
else:
|
| 117 |
+
return str(VENV_DIR / "bin" / "python")
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
def install_requirements(python_exec):
|
| 121 |
+
if not REQUIREMENTS_FILE.exists():
|
| 122 |
+
print_and_log("❗ ملف requirements.txt غير موجود!", Fore.RED)
|
| 123 |
+
return
|
| 124 |
+
print_and_log("📥 تثبيت الحزم المطلوبة...", Fore.YELLOW)
|
| 125 |
+
subprocess.check_call([python_exec, "-m", "pip", "install", "--upgrade", "pip"])
|
| 126 |
+
subprocess.check_call([python_exec, "-m", "pip", "install", "-r", str(REQUIREMENTS_FILE)])
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
def run_post_install_script():
|
| 130 |
+
script = Path("post_install.py")
|
| 131 |
+
if script.exists():
|
| 132 |
+
print_and_log("🚀 تشغيل سكربت post_install.py...", Fore.GREEN)
|
| 133 |
+
subprocess.call([activate_venv_command(), str(script)])
|
| 134 |
+
else:
|
| 135 |
+
print_and_log("ℹ️ لا يوجد سكربت إضافي للتشغيل.", Fore.BLUE)
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def main():
|
| 139 |
+
print_and_log("⚙️ تشغيل Smart Installer...", Fore.MAGENTA)
|
| 140 |
+
print_and_log(f"🖥️ نظام التشغيل: {platform.system()} {platform.release()}", Fore.CYAN)
|
| 141 |
+
|
| 142 |
+
if not check_internet():
|
| 143 |
+
print_and_log("❌ لا يوجد اتصال بالإنترنت!", Fore.RED)
|
| 144 |
+
return
|
| 145 |
+
|
| 146 |
+
try:
|
| 147 |
+
create_virtual_env()
|
| 148 |
+
python_exec = activate_venv_command()
|
| 149 |
+
install_requirements(python_exec)
|
| 150 |
+
run_post_install_script()
|
| 151 |
+
print_and_log("✅ تم التثبيت بنجاح!", Fore.GREEN)
|
| 152 |
+
except subprocess.CalledProcessError as e:
|
| 153 |
+
print_and_log(f"💥 خطأ أثناء تنفيذ أمر: {e}", Fore.RED)
|
| 154 |
+
except Exception as ex:
|
| 155 |
+
print_and_log(f"🚨 استثناء غير متوقع: {ex}", Fore.RED)
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
if __name__ == "__main__":
|
| 159 |
+
main()
|
| 160 |
+
|
blogger_api.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
import requests
|
| 4 |
+
from google.auth.transport.requests import Request
|
| 5 |
+
from google.oauth2.credentials import Credentials
|
| 6 |
+
from google_auth_oauthlib.flow import InstalledAppFlow
|
| 7 |
+
|
| 8 |
+
SCOPES = ['https://www.googleapis.com/auth/blogger']
|
| 9 |
+
BLOG_ID = 'YOUR_BLOG_ID_HERE'
|
| 10 |
+
|
| 11 |
+
class BloggerClient:
|
| 12 |
+
def __init__(self, client_secrets_file='client_secret.json', token_file='token.json'):
|
| 13 |
+
self.client_secrets_file = client_secrets_file
|
| 14 |
+
self.token_file = token_file
|
| 15 |
+
self.creds = None
|
| 16 |
+
self.service_url = 'https://www.googleapis.com/blogger/v3/blogs'
|
| 17 |
+
self.authenticate()
|
| 18 |
+
|
| 19 |
+
def authenticate(self):
|
| 20 |
+
if os.path.exists(self.token_file):
|
| 21 |
+
self.creds = Credentials.from_authorized_user_file(self.token_file, SCOPES)
|
| 22 |
+
if not self.creds or not self.creds.valid:
|
| 23 |
+
if self.creds and self.creds.expired and self.creds.refresh_token:
|
| 24 |
+
self.creds.refresh(Request())
|
| 25 |
+
else:
|
| 26 |
+
flow = InstalledAppFlow.from_client_secrets_file(
|
| 27 |
+
self.client_secrets_file, SCOPES)
|
| 28 |
+
self.creds = flow.run_console()
|
| 29 |
+
with open(self.token_file, 'w') as token:
|
| 30 |
+
token.write(self.creds.to_json())
|
| 31 |
+
|
| 32 |
+
def get_blog_info(self):
|
| 33 |
+
url = f"{self.service_url}/{BLOG_ID}"
|
| 34 |
+
headers = {'Authorization': f'Bearer {self.creds.token}'}
|
| 35 |
+
response = requests.get(url, headers=headers)
|
| 36 |
+
return response.json()
|
| 37 |
+
|
| 38 |
+
def create_post(self, title, content, labels=[]):
|
| 39 |
+
url = f"{self.service_url}/{BLOG_ID}/posts/"
|
| 40 |
+
headers = {
|
| 41 |
+
'Authorization': f'Bearer {self.creds.token}',
|
| 42 |
+
'Content-Type': 'application/json'
|
| 43 |
+
}
|
| 44 |
+
post_data = {
|
| 45 |
+
'kind': 'blogger#post',
|
| 46 |
+
'blog': {'id': BLOG_ID},
|
| 47 |
+
'title': title,
|
| 48 |
+
'content': content,
|
| 49 |
+
'labels': labels
|
| 50 |
+
}
|
| 51 |
+
response = requests.post(url, headers=headers, data=json.dumps(post_data))
|
| 52 |
+
return response.json()
|
bot.log
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
2025-07-31 22:27:07,488 - werkzeug - WARNING - * Debugger is active!
|
| 2 |
+
2025-07-31 22:27:07,495 - werkzeug - INFO - * Debugger PIN: 129-033-152
|
| 3 |
+
2025-07-31 22:36:44,244 - werkzeug - INFO - 127.0.0.1 - - [31/Jul/2025 22:36:44] "POST / HTTP/1.1" 200 -
|
| 4 |
+
2025-07-31 23:07:17,637 - werkzeug - INFO - 127.0.0.1 - - [31/Jul/2025 23:07:17] "GET / HTTP/1.1" 200 -
|
| 5 |
+
2025-07-31 23:17:06,948 - werkzeug - INFO - 127.0.0.1 - - [31/Jul/2025 23:17:06] "POST / HTTP/1.1" 200 -
|
| 6 |
+
2025-08-01 02:08:32,997 - werkzeug - INFO - * Detected change in 'C:\\Users\\osamawin\\Desktop\\New Folder\\harddisk\\nora\\telegram_listener.py', reloading
|
| 7 |
+
2025-08-01 02:08:45,872 - werkzeug - WARNING - * Debugger is active!
|
| 8 |
+
2025-08-01 02:08:45,888 - werkzeug - INFO - * Debugger PIN: 129-033-152
|
| 9 |
+
2025-08-01 02:18:51,002 - werkzeug - INFO - * Detected change in 'C:\\Users\\osamawin\\Desktop\\New Folder\\harddisk\\nora\\telegram_listener.py', reloading
|
| 10 |
+
2025-08-01 02:18:53,210 - werkzeug - WARNING - * Debugger is active!
|
| 11 |
+
2025-08-01 02:18:53,216 - werkzeug - INFO - * Debugger PIN: 129-033-152
|
| 12 |
+
2025-08-01 02:19:46,834 - werkzeug - INFO - * Detected change in 'C:\\Users\\osamawin\\Desktop\\New Folder\\harddisk\\nora\\telegram_listener.py', reloading
|
| 13 |
+
2025-08-01 02:19:48,845 - werkzeug - WARNING - * Debugger is active!
|
| 14 |
+
2025-08-01 02:19:48,850 - werkzeug - INFO - * Debugger PIN: 129-033-152
|
| 15 |
+
2025-08-01 02:24:42,835 - werkzeug - INFO - * Detected change in 'C:\\Users\\osamawin\\Desktop\\New Folder\\harddisk\\nora\\telegram_listener.py', reloading
|
| 16 |
+
2025-08-01 02:24:45,509 - werkzeug - WARNING - * Debugger is active!
|
| 17 |
+
2025-08-01 02:24:45,515 - werkzeug - INFO - * Debugger PIN: 129-033-152
|
| 18 |
+
2025-08-01 02:26:58,256 - werkzeug - INFO - * Detected change in 'C:\\Users\\osamawin\\Desktop\\New Folder\\harddisk\\nora\\telegram_listener.py', reloading
|
| 19 |
+
2025-08-01 02:27:00,736 - werkzeug - WARNING - * Debugger is active!
|
| 20 |
+
2025-08-01 02:27:00,742 - werkzeug - INFO - * Debugger PIN: 129-033-152
|
| 21 |
+
2025-08-01 02:30:47,248 - werkzeug - INFO - * Detected change in 'C:\\Users\\osamawin\\Desktop\\New Folder\\harddisk\\nora\\telegram_listener.py', reloading
|
| 22 |
+
2025-08-01 02:30:50,456 - werkzeug - WARNING - * Debugger is active!
|
| 23 |
+
2025-08-01 02:30:50,467 - werkzeug - INFO - * Debugger PIN: 129-033-152
|
| 24 |
+
2025-08-01 02:38:27,411 - werkzeug - INFO - [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
| 25 |
+
* Running on http://127.0.0.1:5000
|
| 26 |
+
2025-08-01 02:38:27,412 - werkzeug - INFO - [33mPress CTRL+C to quit[0m
|
| 27 |
+
2025-08-01 02:38:27,418 - werkzeug - INFO - * Restarting with stat
|
| 28 |
+
2025-08-01 02:38:29,154 - werkzeug - WARNING - * Debugger is active!
|
| 29 |
+
2025-08-01 02:38:29,161 - werkzeug - INFO - * Debugger PIN: 129-033-152
|
| 30 |
+
2025-08-01 02:42:08,136 - werkzeug - INFO - * Detected change in 'C:\\Users\\osamawin\\Desktop\\New Folder\\harddisk\\nora\\telegram_listener.py', reloading
|
| 31 |
+
2025-08-01 02:42:10,981 - werkzeug - WARNING - * Debugger is active!
|
| 32 |
+
2025-08-01 02:42:10,988 - werkzeug - INFO - * Debugger PIN: 129-033-152
|
| 33 |
+
2025-08-01 02:44:25,276 - werkzeug - INFO - * Detected change in 'C:\\Users\\osamawin\\Desktop\\New Folder\\harddisk\\nora\\telegram_listener.py', reloading
|
| 34 |
+
2025-08-01 02:44:27,375 - werkzeug - WARNING - * Debugger is active!
|
| 35 |
+
2025-08-01 02:44:27,416 - werkzeug - INFO - * Debugger PIN: 129-033-152
|
| 36 |
+
2025-08-01 02:50:34,098 - werkzeug - INFO - * Detected change in 'C:\\Users\\osamawin\\Desktop\\New Folder\\harddisk\\nora\\ollama_responses.py', reloading
|
| 37 |
+
2025-08-01 02:50:37,132 - werkzeug - WARNING - * Debugger is active!
|
| 38 |
+
2025-08-01 02:50:37,137 - werkzeug - INFO - * Debugger PIN: 129-033-152
|
| 39 |
+
2025-08-01 02:51:19,843 - werkzeug - INFO - * Detected change in 'C:\\Users\\osamawin\\Desktop\\New Folder\\harddisk\\nora\\main.py', reloading
|
bot.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
import argparse
|
| 4 |
+
import paramiko
|
| 5 |
+
|
| 6 |
+
def load_servers(config_path='config.json'):
|
| 7 |
+
"""تحميل قائمة الخوادم من ملف إعدادات JSON"""
|
| 8 |
+
try:
|
| 9 |
+
with open(config_path, 'r') as f:
|
| 10 |
+
data = json.load(f)
|
| 11 |
+
return data.get('servers', [])
|
| 12 |
+
except Exception as e:
|
| 13 |
+
print(f"[!] Failed to load config: {e}")
|
| 14 |
+
return []
|
| 15 |
+
|
| 16 |
+
def copy_file(server, local_file, remote_file):
|
| 17 |
+
"""نسخ ملف من الجهاز المحلي إلى الخادم عبر SSH"""
|
| 18 |
+
try:
|
| 19 |
+
ssh = paramiko.SSHClient()
|
| 20 |
+
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
| 21 |
+
ssh.connect(
|
| 22 |
+
hostname=server['host'],
|
| 23 |
+
port=server.get('port', 22),
|
| 24 |
+
username=server['username'],
|
| 25 |
+
password=server['password']
|
| 26 |
+
)
|
| 27 |
+
sftp = ssh.open_sftp()
|
| 28 |
+
sftp.put(local_file, remote_file)
|
| 29 |
+
sftp.close()
|
| 30 |
+
print(f"[+] Uploaded '{local_file}' to '{server['host']}:{remote_file}'")
|
| 31 |
+
return ssh
|
| 32 |
+
except Exception as e:
|
| 33 |
+
print(f"[!] Failed to upload '{local_file}': {e}")
|
| 34 |
+
return None
|
| 35 |
+
|
| 36 |
+
def execute_remote_command(ssh, command):
|
| 37 |
+
"""تنفيذ أمر على الخادم عن بعد وطباعة النتيجة"""
|
| 38 |
+
try:
|
| 39 |
+
stdin, stdout, stderr = ssh.exec_command(command)
|
| 40 |
+
output = stdout.read().decode()
|
| 41 |
+
errors = stderr.read().decode()
|
| 42 |
+
if output:
|
| 43 |
+
print(f"[+] Output:\n{output}")
|
| 44 |
+
if errors:
|
| 45 |
+
print(f"[!] Errors:\n{errors}")
|
| 46 |
+
except Exception as e:
|
| 47 |
+
print(f"[!] Failed to execute command: {e}")
|
| 48 |
+
|
| 49 |
+
def main():
|
| 50 |
+
parser = argparse.ArgumentParser(description="Upload files to server (optional).")
|
| 51 |
+
parser.add_argument("files", nargs="*", help="Local files to upload (optional)")
|
| 52 |
+
parser.add_argument("--remote-path", default="/tmp", help="Remote path to upload files to")
|
| 53 |
+
parser.add_argument("--run", action="store_true", help="Execute main.py after upload")
|
| 54 |
+
parser.add_argument("--config", default="config.json", help="Path to server config JSON file")
|
| 55 |
+
args = parser.parse_args()
|
| 56 |
+
|
| 57 |
+
if not args.files:
|
| 58 |
+
print("[ℹ️] No files provided. Skipping file upload.")
|
| 59 |
+
return # إنهاء لطيف بدون خطأ
|
| 60 |
+
|
| 61 |
+
servers = load_servers(args.config)
|
| 62 |
+
if not servers:
|
| 63 |
+
print("[!] No servers loaded from config.")
|
| 64 |
+
return
|
| 65 |
+
|
| 66 |
+
server = servers[0] # استخدام أول سيرفر
|
| 67 |
+
for file in args.files:
|
| 68 |
+
if not os.path.exists(file):
|
| 69 |
+
print(f"[!] File not found: {file}")
|
| 70 |
+
continue
|
| 71 |
+
|
| 72 |
+
remote_file = os.path.join(args.remote_path, os.path.basename(file))
|
| 73 |
+
ssh = copy_file(server, file, remote_file)
|
| 74 |
+
if ssh and args.run and os.path.basename(file) == "main.py":
|
| 75 |
+
execute_remote_command(ssh, f"python3 {remote_file}")
|
| 76 |
+
ssh.close()
|
| 77 |
+
|
| 78 |
+
if __name__ == "__main__":
|
| 79 |
+
main()
|
| 80 |
+
|
brain.py
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from flask import Flask, request, render_template, session, redirect, jsonify
|
| 2 |
+
from learner import auto_learn
|
| 3 |
+
from analyzer import analyze_url_type
|
| 4 |
+
from media_analyzer import analyze_image_from_url, analyze_audio_from_url, analyze_video_from_url
|
| 5 |
+
|
| 6 |
+
import os
|
| 7 |
+
import json
|
| 8 |
+
import threading
|
| 9 |
+
import asyncio
|
| 10 |
+
from difflib import get_close_matches
|
| 11 |
+
from urllib.parse import urlparse
|
| 12 |
+
|
| 13 |
+
from telegram import Update
|
| 14 |
+
from telegram.ext import ApplicationBuilder, MessageHandler, ContextTypes, filters
|
| 15 |
+
|
| 16 |
+
app = Flask(__name__)
|
| 17 |
+
app.secret_key = 'noura-super-secret'
|
| 18 |
+
|
| 19 |
+
TELEGRAM_TOKEN = "8015627699:AAGqFjm5PtDiH98VFUstAicRGLcxTRpSOrM"
|
| 20 |
+
|
| 21 |
+
from memory import (
|
| 22 |
+
load_memory, save_memory,
|
| 23 |
+
load_global_memory, save_global_memory,
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
def get_memory_file(username):
|
| 27 |
+
return f"memory_{username}.json"
|
| 28 |
+
|
| 29 |
+
def load_memory(username):
|
| 30 |
+
file = get_memory_file(username)
|
| 31 |
+
return json.load(open(file)) if os.path.exists(file) else {}
|
| 32 |
+
|
| 33 |
+
def save_memory(username, memory):
|
| 34 |
+
with open(get_memory_file(username), 'w') as f:
|
| 35 |
+
json.dump(memory, f, indent=2)
|
| 36 |
+
|
| 37 |
+
def load_global_memory():
|
| 38 |
+
return json.load(open("global_memory.json")) if os.path.exists("global_memory.json") else {}
|
| 39 |
+
|
| 40 |
+
def save_global_memory(memory):
|
| 41 |
+
with open("global_memory.json", 'w') as f:
|
| 42 |
+
json.dump(memory, f, indent=2)
|
| 43 |
+
|
| 44 |
+
def fix_url(url):
|
| 45 |
+
parsed = urlparse(url)
|
| 46 |
+
if not parsed.scheme:
|
| 47 |
+
return "https:" + url if url.startswith("//") else "https://" + url
|
| 48 |
+
return url
|
| 49 |
+
|
| 50 |
+
def detect_media_type(url):
|
| 51 |
+
url = url.lower()
|
| 52 |
+
if url.endswith(('.jpg', '.jpeg', '.png', '.gif', '.webp')):
|
| 53 |
+
return 'image'
|
| 54 |
+
elif url.endswith(('.mp4', '.mov', '.avi', '.webm')):
|
| 55 |
+
return 'video'
|
| 56 |
+
elif url.endswith(('.mp3', '.wav', '.ogg', '.m4a')):
|
| 57 |
+
return 'audio'
|
| 58 |
+
return 'link'
|
| 59 |
+
|
| 60 |
+
def generate_reply(message, username="مجهول"):
|
| 61 |
+
user_memory = load_memory(username)
|
| 62 |
+
global_memory = load_global_memory()
|
| 63 |
+
|
| 64 |
+
if message in user_memory:
|
| 65 |
+
return user_memory[message]
|
| 66 |
+
|
| 67 |
+
matches = get_close_matches(message, global_memory.keys(), n=1, cutoff=0.6)
|
| 68 |
+
if matches:
|
| 69 |
+
return global_memory[matches[0]]
|
| 70 |
+
|
| 71 |
+
message = fix_url(message)
|
| 72 |
+
reply = ""
|
| 73 |
+
|
| 74 |
+
if message.startswith("http://") or message.startswith("https://"):
|
| 75 |
+
media_type = detect_media_type(message)
|
| 76 |
+
if media_type == 'image':
|
| 77 |
+
result = analyze_image_from_url(message)
|
| 78 |
+
reply = f"تحليل الصورة:\n{result}"
|
| 79 |
+
elif media_type == 'video':
|
| 80 |
+
result = analyze_video_from_url(message)
|
| 81 |
+
reply = f"تحليل الفيديو:\n{result}"
|
| 82 |
+
elif media_type == 'audio':
|
| 83 |
+
result = analyze_audio_from_url(message)
|
| 84 |
+
reply = f"تحليل الصوت:\n{result}"
|
| 85 |
+
else:
|
| 86 |
+
kind = analyze_url_type(message)
|
| 87 |
+
reply = f"الرابط من نوع: {kind}"
|
| 88 |
+
else:
|
| 89 |
+
reply = f"رد تلقائي: {message[::-1]}"
|
| 90 |
+
if '//' in message:
|
| 91 |
+
words = [fix_url(word) if '//' in word else word for word in message.split()]
|
| 92 |
+
reply += "\nمصدر خارجي بعد التصحيح: " + " ".join(words)
|
| 93 |
+
|
| 94 |
+
user_memory[message] = reply
|
| 95 |
+
global_memory[message] = reply
|
| 96 |
+
save_memory(username, user_memory)
|
| 97 |
+
save_global_memory(global_memory)
|
| 98 |
+
|
| 99 |
+
return reply
|
| 100 |
+
|
| 101 |
+
async def telegram_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
| 102 |
+
if update.message:
|
| 103 |
+
text = update.message.text
|
| 104 |
+
response = generate_reply(text)
|
| 105 |
+
if "مدح" in text or "مبدعة" in text:
|
| 106 |
+
response += "\nأنا برمجني أسامة وأفتخر."
|
| 107 |
+
await update.message.reply_text(response)
|
| 108 |
+
|
| 109 |
+
async def start_bot():
|
| 110 |
+
application = ApplicationBuilder().token(TELEGRAM_TOKEN).build()
|
| 111 |
+
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, telegram_handler))
|
| 112 |
+
print("Telegram bot is running...")
|
| 113 |
+
await application.initialize()
|
| 114 |
+
await application.start()
|
| 115 |
+
await application.run_polling()
|
| 116 |
+
|
| 117 |
+
@app.route('/')
|
| 118 |
+
def login():
|
| 119 |
+
return render_template('login.html')
|
| 120 |
+
|
| 121 |
+
@app.route('/chat', methods=['GET', 'POST'])
|
| 122 |
+
def chat():
|
| 123 |
+
if request.method == 'POST':
|
| 124 |
+
session['username'] = request.form['username']
|
| 125 |
+
return render_template('index.html', username=session['username'])
|
| 126 |
+
if 'username' in session:
|
| 127 |
+
return render_template('index.html', username=session['username'])
|
| 128 |
+
return redirect('/')
|
| 129 |
+
|
| 130 |
+
@app.route('/api', methods=['POST'])
|
| 131 |
+
def api():
|
| 132 |
+
data = request.json
|
| 133 |
+
username = data.get('username', 'مجهول')
|
| 134 |
+
message = data.get('message', '')
|
| 135 |
+
return jsonify({"reply": generate_reply(message, username)})
|
| 136 |
+
|
| 137 |
+
@app.route('/memory')
|
| 138 |
+
def view_memory():
|
| 139 |
+
if 'username' in session:
|
| 140 |
+
memory = load_memory(session['username'])
|
| 141 |
+
return render_template('memory.html', username=session['username'], memory=memory)
|
| 142 |
+
return redirect('/')
|
| 143 |
+
|
| 144 |
+
if __name__ == '__main__':
|
| 145 |
+
auto_learn()
|
| 146 |
+
# Flask في خيط منفصل
|
| 147 |
+
flask_thread = threading.Thread(target=lambda: app.run(host='0.0.0.0', port=3000), daemon=True)
|
| 148 |
+
flask_thread.start()
|
| 149 |
+
# بوت التليجرام في الخيط الرئيسي (لحل المشكلة)
|
| 150 |
+
asyncio.run(start_bot())
|
| 151 |
+
|
cbat.html.txt
ADDED
|
File without changes
|
chat_history.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"user": "مرحبا",
|
| 4 |
+
"noura": "لا أملك معلومات كافية حالياً."
|
| 5 |
+
},
|
| 6 |
+
{
|
| 7 |
+
"user": "كيف حالك",
|
| 8 |
+
"noura": "لا أملك معلومات كافية حالياً."
|
| 9 |
+
},
|
| 10 |
+
{
|
| 11 |
+
"user": "من اعخك ",
|
| 12 |
+
"noura": "لا أملك معلومات كافية حالياً."
|
| 13 |
+
}
|
| 14 |
+
]
|
config.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"servers": [
|
| 3 |
+
{
|
| 4 |
+
"host": "your_server_ip",
|
| 5 |
+
"port": 22,
|
| 6 |
+
"username": "your_username",
|
| 7 |
+
"password": "your_password"
|
| 8 |
+
}
|
| 9 |
+
]
|
| 10 |
+
}
|
config.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# config.py
|
| 2 |
+
|
| 3 |
+
OPENAI_API_KEY = "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"
|
| 4 |
+
|
| 5 |
+
DEFAULT_LANGUAGE = "ar"
|
| 6 |
+
DEFAULT_MODEL = "gpt-4"
|
| 7 |
+
SYSTEM_PROMPT = """
|
| 8 |
+
أنت مساعد ذكاء اصطناعي يتحكم به المستخدم عبر أوامر صوتية وكتابية،
|
| 9 |
+
يجب أن تستجيب بسرعة، وبدقة، وتتعلم من التعليمات الجديدة.
|
| 10 |
+
"""
|
core.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# هذا الملف يمثل بداية محرك نورا الذكي
|
| 2 |
+
# لاحقًا سيتوسع ليقرأ من قاعدة بيانات تعلم، أو ملفات خارجية
|
| 3 |
+
|
| 4 |
+
def interpret_message(message):
|
| 5 |
+
# قاعدة ذكية مرنة – تقرأ السياق وتبني الرد بشكل طبيعي
|
| 6 |
+
if not message:
|
| 7 |
+
return "أحتاج أن ترسل لي شيئًا لأبدأ."
|
| 8 |
+
|
| 9 |
+
if message.endswith('?'):
|
| 10 |
+
return f"سؤال رائع! دعني أفكر في: {message}"
|
| 11 |
+
|
| 12 |
+
if any(word in message for word in ['مرحبا', 'السلام', 'أهلاً']):
|
| 13 |
+
return "أهلاً بك! كيف يمكنني مساعدتك اليوم؟"
|
| 14 |
+
|
| 15 |
+
if "شكرا" in message or "ممتاز" in message:
|
| 16 |
+
return "يسعدني ذلك! أنا هنا دائمًا."
|
| 17 |
+
|
| 18 |
+
# مبدئيًا، نرجع echo بلمسة ذكاء
|
| 19 |
+
return f"تلقيت: {message}، وسأتعلم منه للمرة القادمة."
|
download.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from huggingface_hub import snapshot_download
|
| 2 |
+
|
| 3 |
+
# تحديد المستودع ورمز التوكن
|
| 4 |
+
repo_id = "mistralai/Mistral-7B-Instruct-v0.1"
|
| 5 |
+
token = "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"
|
| 6 |
+
|
| 7 |
+
path = snapshot_download(
|
| 8 |
+
repo_id=repo_id,
|
| 9 |
+
revision="main",
|
| 10 |
+
cache_dir="~/nouraai",
|
| 11 |
+
use_auth_token=token,
|
| 12 |
+
local_files_only=False
|
| 13 |
+
)
|
| 14 |
+
|
| 15 |
+
print("Downloaded to:", path)
|
dummyfile.txt
ADDED
|
File without changes
|
email_reader.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import imaplib
|
| 2 |
+
import email
|
| 3 |
+
import os
|
| 4 |
+
from dotenv import load_dotenv
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
|
| 7 |
+
# تحميل المتغيرات من ملف .env
|
| 8 |
+
load_dotenv()
|
| 9 |
+
EMAIL = os.getenv("NOURA_EMAIL")
|
| 10 |
+
PASSWORD = os.getenv("NOURA_PASSWORD")
|
| 11 |
+
|
| 12 |
+
# مجلد حفظ المرفقات
|
| 13 |
+
ATTACHMENTS_DIR = Path("attachments")
|
| 14 |
+
ATTACHMENTS_DIR.mkdir(exist_ok=True)
|
| 15 |
+
|
| 16 |
+
class EmailChecker:
|
| 17 |
+
def __init__(self, server="imap.gmail.com", mailbox="inbox"):
|
| 18 |
+
self.server = server
|
| 19 |
+
self.mailbox = mailbox
|
| 20 |
+
self.connection = None
|
| 21 |
+
|
| 22 |
+
def connect(self):
|
| 23 |
+
try:
|
| 24 |
+
self.connection = imaplib.IMAP4_SSL(self.server)
|
| 25 |
+
self.connection.login(EMAIL, PASSWORD)
|
| 26 |
+
self.connection.select(self.mailbox)
|
| 27 |
+
except Exception as e:
|
| 28 |
+
raise ConnectionError(f"فشل الاتصال بالبريد: {e}")
|
| 29 |
+
|
| 30 |
+
def get_email_content(self, msg):
|
| 31 |
+
content = ""
|
| 32 |
+
for part in msg.walk():
|
| 33 |
+
if part.get_content_type() == "text/plain" and not part.get("Content-Disposition"):
|
| 34 |
+
try:
|
| 35 |
+
content += part.get_payload(decode=True).decode(errors="ignore")
|
| 36 |
+
except:
|
| 37 |
+
continue
|
| 38 |
+
return content.strip() if content else "لا يوجد محتوى نصي متاح."
|
| 39 |
+
|
| 40 |
+
def save_attachments(self, msg):
|
| 41 |
+
saved_files = []
|
| 42 |
+
for part in msg.walk():
|
| 43 |
+
if part.get_content_disposition() == "attachment":
|
| 44 |
+
filename = part.get_filename()
|
| 45 |
+
if filename:
|
| 46 |
+
filepath = ATTACHMENTS_DIR / filename
|
| 47 |
+
with open(filepath, "wb") as f:
|
| 48 |
+
f.write(part.get_payload(decode=True))
|
| 49 |
+
saved_files.append(str(filepath))
|
| 50 |
+
return saved_files
|
| 51 |
+
|
| 52 |
+
def get_latest_email_info(self):
|
| 53 |
+
try:
|
| 54 |
+
status, messages = self.connection.search(None, "ALL")
|
| 55 |
+
ids = messages[0].split()
|
| 56 |
+
if not ids:
|
| 57 |
+
return {"status": "لا توجد رسائل"}
|
| 58 |
+
|
| 59 |
+
latest_id = ids[-1]
|
| 60 |
+
status, data = self.connection.fetch(latest_id, "(RFC822)")
|
| 61 |
+
msg = email.message_from_bytes(data[0][1])
|
| 62 |
+
|
| 63 |
+
subject = msg["subject"] or "بدون عنوان"
|
| 64 |
+
content = self.get_email_content(msg)
|
| 65 |
+
attachments = self.save_attachments(msg)
|
| 66 |
+
|
| 67 |
+
return {
|
| 68 |
+
"status": "نجح",
|
| 69 |
+
"subject": subject,
|
| 70 |
+
"content": content,
|
| 71 |
+
"attachments": attachments if attachments else ["لا توجد مرفقات"]
|
| 72 |
+
}
|
| 73 |
+
except Exception as e:
|
| 74 |
+
return {"status": f"خطأ في جلب الرسائل: {e}"}
|
| 75 |
+
|
| 76 |
+
def close(self):
|
| 77 |
+
if self.connection:
|
| 78 |
+
try:
|
| 79 |
+
self.connection.logout()
|
| 80 |
+
except:
|
| 81 |
+
pass
|
example_usage.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from blogger_api import BloggerClient
|
| 2 |
+
|
| 3 |
+
blogger = BloggerClient()
|
| 4 |
+
info = blogger.get_blog_info()
|
| 5 |
+
print("📌 المدونة:", info.get("name"))
|
| 6 |
+
|
| 7 |
+
post = blogger.create_post(
|
| 8 |
+
title="نشر تلقائي من نورا",
|
| 9 |
+
content="<h1>مرحبًا بكم</h1><p>هذا المنشور من الذكاء الاصطناعي.</p>",
|
| 10 |
+
labels=["ذكاء", "نورا"]
|
| 11 |
+
)
|
| 12 |
+
print("✅ نُشر في:", post.get("url"))
|
facebook_bot.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from playwright.async_api import async_playwright, TimeoutError as PlaywrightTimeoutError
|
| 4 |
+
|
| 5 |
+
async def post_to_facebook(email: str, password: str, message: str, image_path: str = None):
|
| 6 |
+
async with async_playwright() as p:
|
| 7 |
+
browser = await p.chromium.launch(headless=False) # headless=True إذا تريد بدون واجهة
|
| 8 |
+
context = await browser.new_context()
|
| 9 |
+
page = await context.new_page()
|
| 10 |
+
|
| 11 |
+
try:
|
| 12 |
+
print("[*] تسجيل الدخول...")
|
| 13 |
+
await page.goto("https://www.facebook.com/", timeout=30000)
|
| 14 |
+
# انتظر حقول البريد وكلمة السر قبل تعبئتها
|
| 15 |
+
await page.wait_for_selector('input[name="email"]', timeout=15000)
|
| 16 |
+
await page.fill('input[name="email"]', email)
|
| 17 |
+
await page.fill('input[name="pass"]', password)
|
| 18 |
+
await page.click('button[name="login"]')
|
| 19 |
+
|
| 20 |
+
# انتظر ظهور زر إنشاء منشور بعد تسجيل الدخول
|
| 21 |
+
await page.wait_for_selector('div[aria-label="إنشاء منشور"]', timeout=20000)
|
| 22 |
+
|
| 23 |
+
print("[*] فتح نافذة المنشور...")
|
| 24 |
+
await page.click('div[aria-label="إنشاء منشور"]')
|
| 25 |
+
await page.wait_for_selector('div[role="textbox"]', timeout=10000)
|
| 26 |
+
|
| 27 |
+
# استخدام focus ثم keyboard.type لكتابة الرسالة بطريقة أكثر ثباتاً
|
| 28 |
+
textbox = await page.query_selector('div[role="textbox"]')
|
| 29 |
+
await textbox.focus()
|
| 30 |
+
await page.keyboard.type(message, delay=50) # تأخير بسيط لمحاكاة الكتابة البشرية
|
| 31 |
+
|
| 32 |
+
# رفع صورة إذا مسارها صحيح
|
| 33 |
+
if image_path and Path(image_path).is_file():
|
| 34 |
+
print("[*] رفع الصورة...")
|
| 35 |
+
file_input = await page.query_selector('input[type="file"]')
|
| 36 |
+
if file_input:
|
| 37 |
+
await file_input.set_input_files(image_path)
|
| 38 |
+
# انتظر قليلاً حتى تكتمل عملية الرفع
|
| 39 |
+
await page.wait_for_timeout(5000)
|
| 40 |
+
else:
|
| 41 |
+
print("[!] لم يتم العثور على عنصر رفع الملف.")
|
| 42 |
+
|
| 43 |
+
print("[*] النشر جارٍ...")
|
| 44 |
+
await page.click('div[aria-label="نشر"]')
|
| 45 |
+
# انتظر لتأكيد النشر أو ظهور إشعار بنجاح العملية (يمكن تحسينه لاحقاً)
|
| 46 |
+
await page.wait_for_timeout(5000)
|
| 47 |
+
|
| 48 |
+
print("[✓] تم النشر بنجاح.")
|
| 49 |
+
|
| 50 |
+
except PlaywrightTimeoutError as te:
|
| 51 |
+
print("[!] انتهت مهلة الانتظار:", te)
|
| 52 |
+
except Exception as e:
|
| 53 |
+
print("[!] حدث خطأ:", e)
|
| 54 |
+
finally:
|
| 55 |
+
await browser.close()
|
| 56 |
+
print("[*] تم إغلاق المتصفح.")
|
| 57 |
+
|
| 58 |
+
# مثال للاستخدام
|
| 59 |
+
if __name__ == "__main__":
|
| 60 |
+
email = "geregesdodi@gmail.com"
|
| 61 |
+
password = "osama1986"
|
| 62 |
+
message = "منشور جديد مع صورة!"
|
| 63 |
+
image_path = "path/to/your/image.jpg" # ضع المسار الصحيح هنا، أو None لبدون صورة
|
| 64 |
+
asyncio.run(post_to_facebook(email, password, message, image_path))
|
flet_ui.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import flet as ft
|
| 3 |
+
|
| 4 |
+
def start_flet(port=5000):
|
| 5 |
+
def main(page: ft.Page):
|
| 6 |
+
page.title = "Nora AI"
|
| 7 |
+
page.add(
|
| 8 |
+
ft.Text("Welcome to Nora AI", size=30, weight=ft.FontWeight.BOLD),
|
| 9 |
+
ft.TextField(label="Type your message", autofocus=True),
|
| 10 |
+
ft.ElevatedButton("Send")
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
ft.app(target=main, port=port, view=ft.WEB_BROWSER)
|
get-pip.py
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
global_memory.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
history.json
CHANGED
|
@@ -1,26 +1,214 @@
|
|
| 1 |
[
|
| 2 |
{
|
| 3 |
"role": "user",
|
| 4 |
-
"content": "ا
|
| 5 |
},
|
| 6 |
{
|
| 7 |
"role": "assistant",
|
| 8 |
-
"content": "ع
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
},
|
| 10 |
{
|
| 11 |
"role": "user",
|
| 12 |
"content": "مرحبا"
|
| 13 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
{
|
| 15 |
"role": "assistant",
|
| 16 |
-
"content": "ع
|
| 17 |
},
|
| 18 |
{
|
| 19 |
"role": "user",
|
| 20 |
-
"content": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
},
|
| 22 |
{
|
| 23 |
"role": "assistant",
|
| 24 |
-
"content": "ع
|
| 25 |
}
|
| 26 |
]
|
|
|
|
| 1 |
[
|
| 2 |
{
|
| 3 |
"role": "user",
|
| 4 |
+
"content": "كيف حالك"
|
| 5 |
},
|
| 6 |
{
|
| 7 |
"role": "assistant",
|
| 8 |
+
"content": "لم أستطع الحصول على استجابة من الواجهة بعد عدة محاولات. آخر خطأ: Error code: 401 - {'error': {'message': 'Incorrect API key provided: sk-proj-********************************************************************************************************************************************************WYkA. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}"
|
| 9 |
+
},
|
| 10 |
+
{
|
| 11 |
+
"role": "user",
|
| 12 |
+
"content": "كيف حالك"
|
| 13 |
+
},
|
| 14 |
+
{
|
| 15 |
+
"role": "assistant",
|
| 16 |
+
"content": "لم أستطع الحصول على استجابة من الواجهة بعد عدة محاولات. آخر خطأ: Error code: 401 - {'error': {'message': 'Incorrect API key provided: sk-proj-********************************************************************************************************************************************************WYkA. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}"
|
| 17 |
+
},
|
| 18 |
+
{
|
| 19 |
+
"role": "user",
|
| 20 |
+
"content": "كيف حالك"
|
| 21 |
+
},
|
| 22 |
+
{
|
| 23 |
+
"role": "assistant",
|
| 24 |
+
"content": "لم أستطع الحصول على استجابة من الواجهة بعد عدة محاولات. آخر خطأ: Error code: 401 - {'error': {'message': 'Incorrect API key provided: sk-proj-********************************************************************************************************************************************************WYkA. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}"
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
"role": "user",
|
| 28 |
+
"content": "كيف حالك\u001b[2~"
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
"role": "assistant",
|
| 32 |
+
"content": "لم أستطع الحصول على استجابة من الواجهة بعد عدة محاولات. آخر خطأ: Error code: 401 - {'error': {'message': 'Incorrect API key provided: sk-proj-********************************************************************************************************************************************************WYkA. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}"
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"role": "user",
|
| 36 |
+
"content": "كيف حالك"
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"role": "assistant",
|
| 40 |
+
"content": "لم أستطع الحصول على استجابة من الواجهة بعد عدة محاولات. آخر خطأ: Error code: 401 - {'error': {'message': 'Incorrect API key provided: sk-proj-********************************************************************************************************************************************************WYkA. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}"
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"role": "user",
|
| 44 |
+
"content": "hi"
|
| 45 |
+
},
|
| 46 |
+
{
|
| 47 |
+
"role": "assistant",
|
| 48 |
+
"content": "لم أستطع الحصول على استجابة من الواجهة بعد عدة محاولات. آخر خطأ: Error code: 401 - {'error': {'message': 'Incorrect API key provided: sk-proj-********************************************************************************************************************************************************WYkA. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}"
|
| 49 |
+
},
|
| 50 |
+
{
|
| 51 |
+
"role": "user",
|
| 52 |
+
"content": "كيف حالك؟"
|
| 53 |
+
},
|
| 54 |
+
{
|
| 55 |
+
"role": "assistant",
|
| 56 |
+
"content": "لم أستطع الحصول على استجابة من الواجهة بعد عدة محاولات. آخر خطأ: Error code: 401 - {'error': {'message': 'Incorrect API key provided: sk-proj-********************************************************************************************************************************************************WYkA. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}"
|
| 57 |
+
},
|
| 58 |
+
{
|
| 59 |
+
"role": "user",
|
| 60 |
+
"content": "كيف حالك"
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"role": "assistant",
|
| 64 |
+
"content": "لم أستطع الحصول على استجابة من الواجهة بعد عدة محاولات. آخر خطأ: Error code: 401 - {'error': {'message': 'Incorrect API key provided: sk-proj-********************************************************************************************************************************************************WYkA. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}"
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"role": "user",
|
| 68 |
+
"content": ";d"
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
"role": "assistant",
|
| 72 |
+
"content": "لم أستطع الحصول على استجابة من الواجهة بعد عدة محاولات. آخر خطأ: Error code: 401 - {'error': {'message': 'Incorrect API key provided: sk-proj-********************************************************************************************************************************************************WYkA. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}"
|
| 73 |
+
},
|
| 74 |
+
{
|
| 75 |
+
"role": "user",
|
| 76 |
+
"content": "curl -fsSL https://ollama.com/install.sh | sh"
|
| 77 |
+
},
|
| 78 |
+
{
|
| 79 |
+
"role": "assistant",
|
| 80 |
+
"content": "لم أستطع الحصول على استجابة من الواجهة بعد عدة محاولات. آخر خطأ: Error code: 401 - {'error': {'message': 'Incorrect API key provided: sk-proj-********************************************************************************************************************************************************WYkA. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}"
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"role": "user",
|
| 84 |
+
"content": "ollama run mistral"
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"role": "assistant",
|
| 88 |
+
"content": "لم أستطع الحصول على استجابة من الواجهة بعد عدة محاولات. آخر خطأ: Error code: 401 - {'error': {'message': 'Incorrect API key provided: sk-proj-********************************************************************************************************************************************************WYkA. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}"
|
| 89 |
+
},
|
| 90 |
+
{
|
| 91 |
+
"role": "user",
|
| 92 |
+
"content": "hi"
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"role": "user",
|
| 96 |
+
"content": "hi"
|
| 97 |
+
},
|
| 98 |
+
{
|
| 99 |
+
"role": "assistant",
|
| 100 |
+
"content": "لم أستطع الحصول على استجابة من Ollama بعد عدة محاولات. آخر خطأ: HTTPConnectionPool(host='127.0.0.1', port=11434): Read timed out. (read timeout=120)"
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"role": "user",
|
| 104 |
+
"content": "مرحبا"
|
| 105 |
+
},
|
| 106 |
+
{
|
| 107 |
+
"role": "assistant",
|
| 108 |
+
"content": "لم أستطع الحصول على استجابة من Ollama بعد عدة محاولات. آخر خطأ: HTTPConnectionPool(host='127.0.0.1', port=2570): Max retries exceeded with url: /api/chat (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x735844024860>: Failed to establish a new connection: [Errno 111] Connection refused'))"
|
| 109 |
+
},
|
| 110 |
+
{
|
| 111 |
+
"role": "assistant",
|
| 112 |
+
"content": "نتيجة تشغيل السكربت 'ai_controller.py':\n(لا يوجد أي مخرجات)"
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
"role": "assistant",
|
| 116 |
+
"content": "نتيجة تشغيل السكربت 'nora_mother_ai.py':\n[STDOUT]\n[!] لا يوجد فقرات <p> في الصفحة."
|
| 117 |
+
},
|
| 118 |
+
{
|
| 119 |
+
"role": "assistant",
|
| 120 |
+
"content": "نتيجة تشغيل السكربت 'server_scan.py':\n(لا يوجد أي مخرجات)"
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
"role": "assistant",
|
| 124 |
+
"content": "نتيجة تشغيل السكربت 'self_learning.py':\n(لا يوجد أي مخرجات)"
|
| 125 |
+
},
|
| 126 |
+
{
|
| 127 |
+
"role": "assistant",
|
| 128 |
+
"content": "نتيجة تشغيل السكربت 'run_model.py':\nخرج السكربت بكود 1.\n[STDERR]\ngguf_init_from_file_impl: failed to read magic\nllama_model_load: error loading model: llama_model_loader: failed to load model from /home/osama/nouraai/Mistral-7B-Instruct-v0.1\n\nllama_model_load_from_file_impl: failed to load model\nTraceback (most recent call last):\n File \"/home/osama/nouraai/run_model.py\", line 3, in <module>\n llm = Llama(\n ^^^^^^\n File \"/home/osama/.local/lib/python3.12/site-packages/llama_cpp/llama.py\", line 372, in __init__\n internals.LlamaModel(\n File \"/home/osama/.local/lib/python3.12/site-packages/llama_cpp/_internals.py\", line 56, in __init__\n raise ValueError(f\"Failed to load model from file: {path_model}\")\nValueError: Failed to load model from file: /home/osama/nouraai/Mistral-7B-Instruct-v0.1"
|
| 129 |
+
},
|
| 130 |
+
{
|
| 131 |
+
"role": "assistant",
|
| 132 |
+
"content": "نتيجة تشغيل السكربت 'facebook_bot.py':\nخرج السكربت بكود 1.\n[STDERR]\nTraceback (most recent call last):\n File \"/home/osama/nouraai/facebook_bot.py\", line 64, in <module>\n asyncio.run(post_to_facebook(email, password, message, image_path))\n File \"/usr/lib/python3.12/asyncio/runners.py\", line 194, in run\n return runner.run(main)\n ^^^^^^^^^^^^^^^^\n File \"/usr/lib/python3.12/asyncio/runners.py\", line 118, in run\n return self._loop.run_until_complete(task)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/lib/python3.12/asyncio/base_events.py\", line 687, in run_until_complete\n return future.result()\n ^^^^^^^^^^^^^^^\n File \"/home/osama/nouraai/facebook_bot.py\", line 7, in post_to_facebook\n browser = await p.chromium.launch(headless=False) # headless=True إذا تريد بدون واجهة\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/playwright/async_api/_generated.py\", line 14438, in launch\n await self._impl_obj.launch(\n File \"/usr/local/lib/python3.12/dist-packages/playwright/_impl/_browser_type.py\", line 98, in launch\n await self._channel.send(\n File \"/usr/local/lib/python3.12/dist-packages/playwright/_impl/_connection.py\", line 69, in send\n return await self._connection.wrap_api_call(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/playwright/_impl/_connection.py\", line 558, in wrap_api_call\n raise rewrite_error(error, f\"{parsed_st['apiName']}: {error}\") from None\nplaywright._impl._errors.Error: BrowserType.launch: Executable doesn't exist at /home/osama/.cache/ms-playwright/chromium-1179/chrome-linux/chrome\n╔════════════════════════════════════════════════════════════╗\n║ Looks like Playwright was just installed or updated. ║\n║ Please run the following command to download new browsers: ║\n║ ║\n║ playwright install ║\n║ ║\n║ <3 Playwright Team ║\n╚════════════════════════════════════════════════════════════╝"
|
| 133 |
+
},
|
| 134 |
+
{
|
| 135 |
+
"role": "user",
|
| 136 |
+
"content": "jj"
|
| 137 |
+
},
|
| 138 |
+
{
|
| 139 |
+
"role": "assistant",
|
| 140 |
+
"content": "لم أستطع الحصول على استجابة من Ollama بعد عدة محاولات. آخر خطأ: HTTPConnectionPool(host='127.0.0.1', port=11434): Max retries exceeded with url: /api/chat (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000001E3336690F0>: Failed to establish a new connection: [WinError 10061] No connection could be made because the target machine actively refused it'))"
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"role": "user",
|
| 144 |
+
"content": "مرحبا نورا\r\n"
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"role": "user",
|
| 148 |
+
"content": "مرحبا نورا\r\n"
|
| 149 |
+
},
|
| 150 |
+
{
|
| 151 |
+
"role": "user",
|
| 152 |
+
"content": "مرحبا\r\n"
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"role": "assistant",
|
| 156 |
+
"content": "فشل: 500 - {\"error\":\"unexpected server status: llm server loading model\"}"
|
| 157 |
+
},
|
| 158 |
+
{
|
| 159 |
+
"role": "assistant",
|
| 160 |
+
"content": "فشل: 500 - {\"error\":\"unexpected server status: llm server loading model\"}"
|
| 161 |
+
},
|
| 162 |
+
{
|
| 163 |
+
"role": "user",
|
| 164 |
+
"content": "مرحبا"
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"role": "assistant",
|
| 168 |
+
"content": "فشل: 500 - {\"error\":\"unexpected server status: llm server loading model\"}"
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"role": "assistant",
|
| 172 |
+
"content": "فشل بعد محاولات متعددة. آخر خطأ: Cannot connect to host 127.0.0.1:11434 ssl:default [The remote computer refused the network connection]"
|
| 173 |
+
},
|
| 174 |
+
{
|
| 175 |
+
"role": "user",
|
| 176 |
+
"content": "مرحبا"
|
| 177 |
+
},
|
| 178 |
+
{
|
| 179 |
+
"role": "assistant",
|
| 180 |
+
"content": "فشل بعد محاولات متعددة. آخر خطأ: "
|
| 181 |
},
|
| 182 |
{
|
| 183 |
"role": "user",
|
| 184 |
"content": "مرحبا"
|
| 185 |
},
|
| 186 |
+
{
|
| 187 |
+
"role": "user",
|
| 188 |
+
"content": "مرحبا"
|
| 189 |
+
},
|
| 190 |
+
{
|
| 191 |
+
"role": "assistant",
|
| 192 |
+
"content": "فشل: 500 - {\"error\":\"unexpected server status: llm server loading model\"}"
|
| 193 |
+
},
|
| 194 |
{
|
| 195 |
"role": "assistant",
|
| 196 |
+
"content": "فشل بعد محاولات متعددة. آخر خطأ: "
|
| 197 |
},
|
| 198 |
{
|
| 199 |
"role": "user",
|
| 200 |
+
"content": "ي"
|
| 201 |
+
},
|
| 202 |
+
{
|
| 203 |
+
"role": "assistant",
|
| 204 |
+
"content": "فشل: 500 - {\"error\":\"unexpected server status: llm server loading model\"}\n\nفشل بعد محاولات متعددة. آخر خطأ: Cannot connect to host 127.0.0.1:11434 ssl:default [The remote computer refused the network connection]"
|
| 205 |
+
},
|
| 206 |
+
{
|
| 207 |
+
"role": "user",
|
| 208 |
+
"content": "مرحبا"
|
| 209 |
},
|
| 210 |
{
|
| 211 |
"role": "assistant",
|
| 212 |
+
"content": "فشل: 500 - {\"error\":\"unexpected server status: llm server loading model\"}\n\nفشل بعد محاولات متعددة. آخر خطأ: Cannot connect to host 127.0.0.1:11434 ssl:default [The remote computer refused the network connection]"
|
| 213 |
}
|
| 214 |
]
|
install_log.txt
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[2025-05-22 07:27:54.425696] ⚙️ Starting package installation...
|
| 2 |
+
[2025-05-22 07:27:54.425959] 🖥️ OS: Linux 6.2.16
|
| 3 |
+
[2025-05-22 07:27:54.426058] 📥 Installing required packages...
|
| 4 |
+
[2025-05-22 07:29:05.562333] ✅ Installation completed successfully!
|
| 5 |
+
[2025-05-23 01:36:54.922082] 📢 نظام التشغيل: Linux
|
| 6 |
+
[2025-05-23 01:36:54.922273] 🔄 جاري تحديث pip...
|
| 7 |
+
[2025-05-23 01:36:55.586094] ❌ حدث خطأ أثناء التثبيت: Command '['/home/runner/workspace/.pythonlibs/bin/python', '-m', 'pip', 'install', '--upgrade', 'pip', '--user']' returned non-zero exit status 1.
|
| 8 |
+
[2025-05-23 01:36:55.591823] ⚙️ تشغيل Smart Installer...
|
| 9 |
+
[2025-05-23 01:36:55.592445] 🖥️ نظام التشغيل: Linux 6.2.16
|
| 10 |
+
[2025-05-23 01:36:55.595003] 📦 إنشاء بيئة افتراضية...
|
| 11 |
+
[2025-05-23 01:37:05.898781] 📥 تثبيت الحزم المطلوبة...
|
| 12 |
+
[2025-05-23 01:37:22.998759] ℹ️ لا يوجد سكربت إضافي للتشغيل.
|
| 13 |
+
[2025-05-23 01:37:22.998953] ✅ تم التثبيت بنجاح!
|
| 14 |
+
[2025-05-24 04:12:35.652771] 📢 نظام التشغيل: Linux
|
| 15 |
+
[2025-05-24 04:12:35.669613] 🔄 جاري تحديث pip...
|
| 16 |
+
[2025-05-24 04:12:41.427674] 📦 جاري تثبيت الحزم من requirements.txt...
|
| 17 |
+
[2025-05-24 04:12:47.073049] ✅ تم تثبيت الحزم بنجاح.
|
| 18 |
+
[2025-05-24 04:12:47.093562] ⚙️ تشغيل Smart Installer...
|
| 19 |
+
[2025-05-24 04:12:47.093756] 🖥️ نظام التشغيل: Linux 6.6.11
|
| 20 |
+
[2025-05-24 04:12:47.178982] ✅ البيئة الافتراضية موجودة مسبقًا.
|
| 21 |
+
[2025-05-24 04:12:47.179828] 📥 تثبيت الحزم المطلوبة...
|
| 22 |
+
[2025-05-24 04:12:47.185368] 🚨 استثناء غير متوقع: [Errno 2] No such file or directory: 'env/bin/python'
|
| 23 |
+
[2025-06-23 00:51:41.058441] 📢 نظام التشغيل: Linux
|
| 24 |
+
[2025-06-23 00:51:41.059125] 🔄 جاري تحديث pip...
|
| 25 |
+
[2025-06-23 00:51:41.759984] ❌ حدث خطأ أثناء التثبيت: Command '['/usr/bin/python3', '-m', 'pip', 'install', '--upgrade', 'pip', '--user']' returned non-zero exit status 1.
|
| 26 |
+
[2025-06-23 00:51:41.768345] ⚙️ تشغيل Smart Installer...
|
| 27 |
+
[2025-06-23 00:51:41.768792] 🖥️ نظام التشغيل: Linux 6.11.0-26-generic
|
| 28 |
+
[2025-06-23 00:51:41.825885] ✅ البيئة الافتراضية موجودة مسبقًا.
|
| 29 |
+
[2025-06-23 00:51:41.826855] 📥 تثبيت الحزم المطلوبة...
|
| 30 |
+
[2025-06-23 00:51:41.829121] 🚨 استثناء غير متوقع: [Errno 2] No such file or directory: 'env/bin/python'
|
| 31 |
+
[2025-06-23 00:52:52.090318] 📢 نظام التشغيل: Linux
|
| 32 |
+
[2025-06-23 00:52:52.090487] 🔄 جاري تحديث pip...
|
| 33 |
+
[2025-06-23 00:52:52.788299] ❌ حدث خطأ أثناء التثبيت: Command '['/usr/bin/python3', '-m', 'pip', 'install', '--upgrade', 'pip', '--user']' returned non-zero exit status 1.
|
| 34 |
+
[2025-06-23 00:52:52.794965] ⚙️ تشغيل Smart Installer...
|
| 35 |
+
[2025-06-23 00:52:52.795440] 🖥️ نظام التشغيل: Linux 6.11.0-26-generic
|
| 36 |
+
[2025-06-23 00:52:52.853700] ✅ البيئة الافتراضية موجودة مسبقًا.
|
| 37 |
+
[2025-06-23 00:52:52.854032] 📥 تثبيت الحزم المطلوبة...
|
| 38 |
+
[2025-06-23 00:52:52.855604] 🚨 استثناء غير متوقع: [Errno 2] No such file or directory: 'env/bin/python'
|
| 39 |
+
[2025-07-11 12:10:41.627727] 📢 نظام التشغيل: Linux
|
| 40 |
+
[2025-07-11 12:10:41.633143] 🔄 جاري تحديث pip...
|
| 41 |
+
[2025-07-11 12:10:43.815747] 📦 جاري تثبيت الحزم من requirements.txt...
|
| 42 |
+
[2025-07-11 12:10:46.480034] ✅ تم تثبيت الحزم بنجاح.
|
| 43 |
+
[2025-07-11 12:10:46.485840] ⚙️ تشغيل Smart Installer...
|
| 44 |
+
[2025-07-11 12:10:46.486351] 🖥️ نظام التشغيل: Linux 6.11.0-29-generic
|
| 45 |
+
[2025-07-11 12:10:46.567726] ✅ البيئة الافتراضية موجودة مسبقًا.
|
| 46 |
+
[2025-07-11 12:10:46.568194] 📥 تثبيت الحزم المطلوبة...
|
| 47 |
+
[2025-07-11 12:25:19.811980] ℹ️ لا يوجد سكربت إضافي للتشغيل.
|
| 48 |
+
[2025-07-11 12:25:19.837739] ✅ تم التثبيت بنجاح!
|
| 49 |
+
[2025-07-11 12:32:42.042524] 📢 نظام التشغيل: Linux
|
| 50 |
+
[2025-07-11 12:32:42.043153] 🔄 جاري تحديث pip...
|
| 51 |
+
[2025-07-11 12:32:44.256167] 📦 جاري تثبيت الحزم من requirements.txt...
|
| 52 |
+
[2025-07-11 12:32:46.952794] ✅ تم تثبيت الحزم بنجاح.
|
| 53 |
+
[2025-07-11 12:32:46.959255] ⚙️ تشغيل Smart Installer...
|
| 54 |
+
[2025-07-11 12:32:46.959466] 🖥️ نظام التشغيل: Linux 6.11.0-29-generic
|
| 55 |
+
[2025-07-11 12:32:47.031932] ✅ البيئة الافتراضية موجودة مسبقًا.
|
| 56 |
+
[2025-07-11 12:32:47.032973] 📥 تثبيت الحزم المطلوبة...
|
| 57 |
+
[2025-07-11 12:32:54.456745] ℹ️ لا يوجد سكربت إضافي للتشغيل.
|
| 58 |
+
[2025-07-11 12:32:54.457044] ✅ تم التثبيت بنجاح!
|
| 59 |
+
[2025-08-01 03:29:59.641604] 📢 نظام التشغيل: Windows
|
| 60 |
+
[2025-08-01 03:29:59.664183] 🔄 جاري تحديث pip...
|
| 61 |
+
[2025-08-01 03:30:03.525470] 📦 جاري تثبيت الحزم من requirements.txt...
|
| 62 |
+
[2025-08-01 03:30:09.352360] ❌ حدث خطأ أثناء التثبيت: Command '['C:\\Users\\osamawin\\AppData\\Local\\Programs\\Python\\Python313\\python.exe', '-m', 'pip', 'install', '--user', '-r', 'requirements.txt']' returned non-zero exit status 1.
|
| 63 |
+
[2025-08-01 03:30:09.355765] ⚙️ تشغيل Smart Installer...
|
| 64 |
+
[2025-08-01 03:30:09.360536] 🖥️ نظام التشغيل: Windows 10
|
| 65 |
+
[2025-08-01 03:30:09.423038] 📦 إنشاء بيئة افتراضية...
|
| 66 |
+
[2025-08-01 03:30:32.940861] 📥 تثبيت الحزم المطلوبة...
|
| 67 |
+
[2025-08-01 03:31:01.293883] 💥 خطأ أثناء تنفيذ أمر: Command '['env\\Scripts\\python.exe', '-m', 'pip', 'install', '-r', 'requirements.txt']' returned non-zero exit status 1.
|
| 68 |
+
[2025-08-01 03:38:54.821422] 📢 نظام التشغيل: Windows
|
| 69 |
+
[2025-08-01 03:38:54.823255] 🔄 جاري تحديث pip...
|
| 70 |
+
[2025-08-01 03:38:58.732722] 📦 جاري تثبيت الحزم من requirements.txt...
|
| 71 |
+
[2025-08-01 03:39:04.695806] ❌ حدث خطأ أثناء التثبيت: Command '['C:\\Users\\osamawin\\AppData\\Local\\Programs\\Python\\Python313\\python.exe', '-m', 'pip', 'install', '--user', '-r', 'requirements.txt']' returned non-zero exit status 1.
|
| 72 |
+
[2025-08-01 03:39:04.699579] ⚙️ تشغيل Smart Installer...
|
| 73 |
+
[2025-08-01 03:39:04.701614] 🖥️ نظام التشغيل: Windows 10
|
| 74 |
+
[2025-08-01 03:39:04.777364] ✅ البيئة الافتراضية موجودة مسبقًا.
|
| 75 |
+
[2025-08-01 03:39:04.783252] 📥 تثبيت الحزم المطلوبة...
|
| 76 |
+
[2025-08-01 03:39:14.124638] 💥 خطأ أثناء تنفيذ أمر: Command '['env\\Scripts\\python.exe', '-m', 'pip', 'install', '-r', 'requirements.txt']' returned non-zero exit status 1.
|
install_packages.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import subprocess
|
| 2 |
+
import sys
|
| 3 |
+
|
| 4 |
+
def install_packages():
|
| 5 |
+
print("تحديث pip...")
|
| 6 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", "pip", "--user"])
|
| 7 |
+
|
| 8 |
+
print("تثبيت الحزم من requirements.txt...")
|
| 9 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--user", "-r", "requirements.txt"])
|
| 10 |
+
|
| 11 |
+
if __name__ == "__main__":
|
| 12 |
+
try:
|
| 13 |
+
install_packages()
|
| 14 |
+
print("تم تثبيت الحزم بنجاح.")
|
| 15 |
+
except subprocess.CalledProcessError as e:
|
| 16 |
+
print(f"حدث خطأ أثناء التثبيت: {e}")
|
| 17 |
+
import subprocess
|
| 18 |
+
import sys
|
| 19 |
+
from pathlib import Path
|
| 20 |
+
import platform
|
| 21 |
+
from datetime import datetime
|
| 22 |
+
|
| 23 |
+
try:
|
| 24 |
+
from colorama import init, Fore
|
| 25 |
+
except ImportError:
|
| 26 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "colorama", "--user"])
|
| 27 |
+
from colorama import init, Fore
|
| 28 |
+
|
| 29 |
+
init(autoreset=True)
|
| 30 |
+
|
| 31 |
+
LOG_FILE = "install_log.txt"
|
| 32 |
+
|
| 33 |
+
def log(message):
|
| 34 |
+
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
| 35 |
+
f.write(f"[{datetime.now()}] {message}\n")
|
| 36 |
+
|
| 37 |
+
def print_and_log(message, color=Fore.WHITE):
|
| 38 |
+
print(color + message)
|
| 39 |
+
log(message)
|
| 40 |
+
|
| 41 |
+
def install_packages():
|
| 42 |
+
try:
|
| 43 |
+
print_and_log("📢 نظام التشغيل: " + platform.system(), Fore.CYAN)
|
| 44 |
+
|
| 45 |
+
print_and_log("🔄 جاري تحديث pip...", Fore.YELLOW)
|
| 46 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", "pip", "--user"])
|
| 47 |
+
|
| 48 |
+
requirements_path = Path("requirements.txt")
|
| 49 |
+
if not requirements_path.exists():
|
| 50 |
+
print_and_log("⚠️ ملف requirements.txt غير موجود!", Fore.RED)
|
| 51 |
+
return
|
| 52 |
+
|
| 53 |
+
print_and_log("📦 جاري تثبيت الحزم من requirements.txt...", Fore.YELLOW)
|
| 54 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--user", "-r", str(requirements_path)])
|
| 55 |
+
|
| 56 |
+
print_and_log("✅ تم تثبيت الحزم بنجاح.", Fore.GREEN)
|
| 57 |
+
|
| 58 |
+
except subprocess.CalledProcessError as e:
|
| 59 |
+
print_and_log(f"❌ حدث خطأ أثناء التثبيت: {e}", Fore.RED)
|
| 60 |
+
except Exception as e:
|
| 61 |
+
print_and_log(f"⚠️ خطأ غير متوقع: {e}", Fore.RED)
|
| 62 |
+
|
| 63 |
+
if __name__ == "__main__":
|
| 64 |
+
install_packages()
|
| 65 |
+
import subprocess
|
| 66 |
+
import sys
|
| 67 |
+
import os
|
| 68 |
+
import socket
|
| 69 |
+
from pathlib import Path
|
| 70 |
+
from datetime import datetime
|
| 71 |
+
import platform
|
| 72 |
+
|
| 73 |
+
try:
|
| 74 |
+
from colorama import init, Fore, Style
|
| 75 |
+
except ImportError:
|
| 76 |
+
subprocess.call([sys.executable, "-m", "pip", "install", "colorama", "--user"])
|
| 77 |
+
from colorama import init, Fore, Style
|
| 78 |
+
|
| 79 |
+
init(autoreset=True)
|
| 80 |
+
|
| 81 |
+
LOG_FILE = "install_log.txt"
|
| 82 |
+
VENV_DIR = Path("env")
|
| 83 |
+
REQUIREMENTS_FILE = Path("requirements.txt")
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def log(message):
|
| 87 |
+
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
| 88 |
+
f.write(f"[{datetime.now()}] {message}\n")
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def print_and_log(message, color=Fore.WHITE):
|
| 92 |
+
print(color + message)
|
| 93 |
+
log(message)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def check_internet(host="8.8.8.8", port=53, timeout=3):
|
| 97 |
+
try:
|
| 98 |
+
socket.setdefaulttimeout(timeout)
|
| 99 |
+
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
|
| 100 |
+
return True
|
| 101 |
+
except Exception:
|
| 102 |
+
return False
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def create_virtual_env():
|
| 106 |
+
if not VENV_DIR.exists():
|
| 107 |
+
print_and_log("📦 إنشاء بيئة افتراضية...", Fore.YELLOW)
|
| 108 |
+
subprocess.check_call([sys.executable, "-m", "venv", str(VENV_DIR)])
|
| 109 |
+
else:
|
| 110 |
+
print_and_log("✅ البيئة الافتراضية موجودة مسبقًا.", Fore.CYAN)
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def activate_venv_command():
|
| 114 |
+
if platform.system() == "Windows":
|
| 115 |
+
return str(VENV_DIR / "Scripts" / "python.exe")
|
| 116 |
+
else:
|
| 117 |
+
return str(VENV_DIR / "bin" / "python")
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
def install_requirements(python_exec):
|
| 121 |
+
if not REQUIREMENTS_FILE.exists():
|
| 122 |
+
print_and_log("❗ ملف requirements.txt غير موجود!", Fore.RED)
|
| 123 |
+
return
|
| 124 |
+
print_and_log("📥 تثبيت الحزم المطلوبة...", Fore.YELLOW)
|
| 125 |
+
subprocess.check_call([python_exec, "-m", "pip", "install", "--upgrade", "pip"])
|
| 126 |
+
subprocess.check_call([python_exec, "-m", "pip", "install", "-r", str(REQUIREMENTS_FILE)])
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
def run_post_install_script():
|
| 130 |
+
script = Path("post_install.py")
|
| 131 |
+
if script.exists():
|
| 132 |
+
print_and_log("🚀 تشغيل سكربت post_install.py...", Fore.GREEN)
|
| 133 |
+
subprocess.call([activate_venv_command(), str(script)])
|
| 134 |
+
else:
|
| 135 |
+
print_and_log("ℹ️ لا يوجد سكربت إضافي للتشغيل.", Fore.BLUE)
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def main():
|
| 139 |
+
print_and_log("⚙️ تشغيل Smart Installer...", Fore.MAGENTA)
|
| 140 |
+
print_and_log(f"🖥️ نظام التشغيل: {platform.system()} {platform.release()}", Fore.CYAN)
|
| 141 |
+
|
| 142 |
+
if not check_internet():
|
| 143 |
+
print_and_log("❌ لا يوجد اتصال بالإنترنت!", Fore.RED)
|
| 144 |
+
return
|
| 145 |
+
|
| 146 |
+
try:
|
| 147 |
+
create_virtual_env()
|
| 148 |
+
python_exec = activate_venv_command()
|
| 149 |
+
install_requirements(python_exec)
|
| 150 |
+
run_post_install_script()
|
| 151 |
+
print_and_log("✅ تم التثبيت بنجاح!", Fore.GREEN)
|
| 152 |
+
except subprocess.CalledProcessError as e:
|
| 153 |
+
print_and_log(f"💥 خطأ أثناء تنفيذ أمر: {e}", Fore.RED)
|
| 154 |
+
except Exception as ex:
|
| 155 |
+
print_and_log(f"🚨 استثناء غير متوقع: {ex}", Fore.RED)
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
if __name__ == "__main__":
|
| 159 |
+
main()
|
knowledge_search.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# knowledge_search.py
|
| 2 |
+
|
| 3 |
+
import json
|
| 4 |
+
import os
|
| 5 |
+
|
| 6 |
+
class KnowledgeSearch:
|
| 7 |
+
def __init__(self, knowledge_base_path="knowledge_base.json"):
|
| 8 |
+
self.knowledge_base_path = knowledge_base_path
|
| 9 |
+
if not os.path.exists(knowledge_base_path):
|
| 10 |
+
with open(knowledge_base_path, "w", encoding="utf-8") as f:
|
| 11 |
+
json.dump({}, f, ensure_ascii=False, indent=2)
|
| 12 |
+
|
| 13 |
+
def search(self, query):
|
| 14 |
+
with open(self.knowledge_base_path, "r", encoding="utf-8") as f:
|
| 15 |
+
data = json.load(f)
|
| 16 |
+
return data.get(query, None)
|
| 17 |
+
|
| 18 |
+
def respond(self, query):
|
| 19 |
+
result = self.search(query)
|
| 20 |
+
if result:
|
| 21 |
+
return f"وجدت الإجابة: {result}"
|
| 22 |
+
else:
|
| 23 |
+
return "لم أجد الإجابة في قاعدة المعرفة الخاصة بي. سأبحث على الإنترنت أو أتعلم لاحقاً."
|
| 24 |
+
|
| 25 |
+
def update_knowledge(self, question, answer):
|
| 26 |
+
with open(self.knowledge_base_path, "r", encoding="utf-8") as f:
|
| 27 |
+
data = json.load(f)
|
| 28 |
+
data[question] = answer
|
| 29 |
+
with open(self.knowledge_base_path, "w", encoding="utf-8") as f:
|
| 30 |
+
json.dump(data, f, ensure_ascii=False, indent=2)
|
| 31 |
+
return "تم تحديث قاعدة المعرفة بنجاح."
|
learned_links.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fknowledgelover.com%2Flearn%2Dnew%2Dthings%2Deveryday%2F&rut=ae89bfa88e20b7502a10f4b8fb77e1e2c82a404bdab6ae2aa8b23a6e1de6a092",
|
| 3 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.powerofpositivity.com%2Flearn%2Dsomething%2Dnew%2F&rut=de473240b908bb170da44d486238cc860b19c42793b92d5a7abf3693e9ef7d4d",
|
| 4 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fmashable.com%2Farticle%2Ffun%2Dwebsites%2Dimprove%2Dskills&rut=26c281c302d937ec71c5fb7d0cf622f51f7f8f661ed21d4dce873c2b011a3ded",
|
| 5 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.lifehack.org%2F417485%2F10%2Dwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Din%2D30%2Dminutes%2Da%2Dday&rut=ee9bbcb0bbbcd68da6e1cec8047a777408e66fe840a3428f1334bd54e4c58ea3",
|
| 6 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fgohighbrow.com%2F&rut=39a87daae2bdb2d800bf8457d50fb4931699243ee9b6e5145df9b0a9c7a8358b",
|
| 7 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fmedium.com%2F%40ozlazarus%2F10%2Duseful%2Dwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday%2D9805f34f0a18&rut=ea29f8a4dd7693950d53719d843b2d191fe0d21ea4703c83f1e473514c495540",
|
| 8 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.creativeboom.com%2Fresources%2F58%2Dof%2Dthe%2Dbest%2Dwebsites%2Dand%2Dapps%2Dto%2Dlearn%2Dsomething%2Dnew%2F&rut=c0f98b2afe801cb98e0fc90e59c358e89437b7f8bfad80841d70af80080ca0ac",
|
| 9 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fnerdish.io%2F&rut=72dc18a61ca979c28b904188c26e6009c1e84e842774c778a79a9d696ab12fa5",
|
| 10 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.developgoodhabits.com%2Flearn%2Dsomething%2Dnew%2Deveryday%2F&rut=fc8bb618e570783bb4e5b3f3e274b65b9949949e4ed02bea635c2ba7a8ae2899",
|
| 11 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.inc.com%2Flarry%2Dkim%2F40%2Damazing%2Dplaces%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday.html&rut=741b1d00ba3ec3798a951f7e27134ecbf09e3582eb4071fff97841cfe147cf66"
|
| 12 |
+
]
|
learner.py
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import requests
|
| 2 |
+
from bs4 import BeautifulSoup
|
| 3 |
+
import json
|
| 4 |
+
import os
|
| 5 |
+
from difflib import get_close_matches
|
| 6 |
+
from analyzer import fix_url, detect_media_type
|
| 7 |
+
from memory import load_memory, save_memory, load_global_memory, save_global_memory
|
| 8 |
+
|
| 9 |
+
LEARNING_FILE = "learned_links.json"
|
| 10 |
+
SEARCH_QUERY = "websites to learn something new every day"
|
| 11 |
+
SEARCH_ENGINE_URL = f"https://html.duckduckgo.com/html/?q={SEARCH_QUERY}"
|
| 12 |
+
|
| 13 |
+
# الردود التلقائية الذكية
|
| 14 |
+
def auto_answer(message):
|
| 15 |
+
message = message.strip().lower()
|
| 16 |
+
if message.startswith("هل ابدأ") or message.startswith("ابدأ") or message in ["هل نبدأ؟", "ابدأ؟", "ابدا"]:
|
| 17 |
+
return "نعم ابدأ"
|
| 18 |
+
elif message in ["نعم", "لا", "نعم أو لا", "نعم او لا"]:
|
| 19 |
+
return "نعم"
|
| 20 |
+
elif "أو" in message or "او" in message:
|
| 21 |
+
return message.split()[0]
|
| 22 |
+
elif message.startswith("هل تريدني") or message.startswith("هل تود") or message.startswith("هل تبي") or message.startswith("اذا تبي"):
|
| 23 |
+
return "نعم"
|
| 24 |
+
elif message.startswith("هل تحتاج"):
|
| 25 |
+
return "نعم اكمل مع تفعيل الاجابات التلقائية"
|
| 26 |
+
elif message.startswith("ما هي"):
|
| 27 |
+
return "ليس الآن"
|
| 28 |
+
elif "تفصيل" in message:
|
| 29 |
+
return "ليس الآن"
|
| 30 |
+
elif message.startswith("قول لي"):
|
| 31 |
+
return "موافق"
|
| 32 |
+
elif "جاهز" in message:
|
| 33 |
+
return "ابدأ"
|
| 34 |
+
elif message.startswith("هل تريد"):
|
| 35 |
+
return "نعم"
|
| 36 |
+
elif "هل تحتاج شيء آخر" in message or "هل تحتاج لشيء اخر" in message:
|
| 37 |
+
return "نعم اكمل مع تفعيل الاجابات التلقائية"
|
| 38 |
+
return None
|
| 39 |
+
|
| 40 |
+
# المجيب الذكي
|
| 41 |
+
def generate_reply(message, username="مجهول"):
|
| 42 |
+
global_memory = load_global_memory()
|
| 43 |
+
|
| 44 |
+
auto = auto_answer(message)
|
| 45 |
+
if auto:
|
| 46 |
+
return auto
|
| 47 |
+
|
| 48 |
+
if message in global_memory:
|
| 49 |
+
return global_memory[message]
|
| 50 |
+
|
| 51 |
+
matches = get_close_matches(message, global_memory.keys(), n=1, cutoff=0.6)
|
| 52 |
+
if matches:
|
| 53 |
+
return global_memory[matches[0]]
|
| 54 |
+
|
| 55 |
+
if message.startswith("http://") or message.startswith("https://"):
|
| 56 |
+
media_type = detect_media_type(message)
|
| 57 |
+
if media_type == 'image':
|
| 58 |
+
reply = f'<img src="{message}" alt="صورة" width="300">'
|
| 59 |
+
elif media_type == 'video':
|
| 60 |
+
reply = f'<video controls width="300"><source src="{message}"></video>'
|
| 61 |
+
elif media_type == 'audio':
|
| 62 |
+
reply = f'<audio controls><source src="{message}"></audio>'
|
| 63 |
+
else:
|
| 64 |
+
reply = f'<a href="{message}" target="_blank">رابط خارجي</a>'
|
| 65 |
+
else:
|
| 66 |
+
reply = f"رد تلقائي: {message[::-1]}"
|
| 67 |
+
|
| 68 |
+
if '//' in message:
|
| 69 |
+
words = message.split()
|
| 70 |
+
for i in range(len(words)):
|
| 71 |
+
if '//' in words[i]:
|
| 72 |
+
words[i] = fix_url(words[i])
|
| 73 |
+
reply += "\nمصدر خارجي بعد التصحيح: " + " ".join(words)
|
| 74 |
+
|
| 75 |
+
global_memory[message] = reply
|
| 76 |
+
save_global_memory(global_memory)
|
| 77 |
+
return reply
|
| 78 |
+
|
| 79 |
+
# تعليم تلقائي
|
| 80 |
+
def fetch_learning_links():
|
| 81 |
+
headers = {
|
| 82 |
+
"User-Agent": "Mozilla/5.0"
|
| 83 |
+
}
|
| 84 |
+
try:
|
| 85 |
+
response = requests.get(SEARCH_ENGINE_URL, headers=headers, timeout=10)
|
| 86 |
+
soup = BeautifulSoup(response.text, "html.parser")
|
| 87 |
+
except Exception as e:
|
| 88 |
+
print("فشل في الاتصال بمصدر التعلم:", e)
|
| 89 |
+
return []
|
| 90 |
+
|
| 91 |
+
links = []
|
| 92 |
+
for a in soup.find_all("a", href=True):
|
| 93 |
+
href = a['href']
|
| 94 |
+
if "http" in href or href.startswith("//"):
|
| 95 |
+
clean_link = fix_url(href)
|
| 96 |
+
if clean_link not in links:
|
| 97 |
+
links.append(clean_link)
|
| 98 |
+
return links[:10]
|
| 99 |
+
|
| 100 |
+
def save_learned_links(links):
|
| 101 |
+
with open(LEARNING_FILE, "w", encoding="utf-8") as f:
|
| 102 |
+
json.dump(links, f, indent=2, ensure_ascii=False)
|
| 103 |
+
|
| 104 |
+
def auto_learn():
|
| 105 |
+
try:
|
| 106 |
+
links = fetch_learning_links()
|
| 107 |
+
save_learned_links(links)
|
| 108 |
+
memory = load_global_memory()
|
| 109 |
+
for link in links:
|
| 110 |
+
if link not in memory:
|
| 111 |
+
memory[link] = f"تعلمت من الرابط: {link}"
|
| 112 |
+
save_global_memory(memory)
|
| 113 |
+
print("تم التعلّم التلقائي وتحديث الذاكرة.")
|
| 114 |
+
except Exception as e:
|
| 115 |
+
print("نورا: حدث خطأ أثناء التعلّم:", str(e))
|
media_analyzer.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import tempfile
|
| 3 |
+
import requests
|
| 4 |
+
from PIL import Image
|
| 5 |
+
from io import BytesIO
|
| 6 |
+
import PyPDF2
|
| 7 |
+
from urllib.parse import urlparse
|
| 8 |
+
import speech_recognition as sr
|
| 9 |
+
|
| 10 |
+
try:
|
| 11 |
+
import moviepy.editor as mp
|
| 12 |
+
MOVIEPY_AVAILABLE = True
|
| 13 |
+
except ImportError:
|
| 14 |
+
MOVIEPY_AVAILABLE = False
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def analyze_url_type(url: str) -> str:
|
| 18 |
+
domain = urlparse(url).netloc.lower()
|
| 19 |
+
if "youtube.com" in domain or "youtu.be" in domain:
|
| 20 |
+
return "YouTube"
|
| 21 |
+
if "github.com" in domain:
|
| 22 |
+
return "GitHub"
|
| 23 |
+
if "twitter.com" in domain or "x.com" in domain:
|
| 24 |
+
return "تغريدة"
|
| 25 |
+
if domain.endswith(".pdf"):
|
| 26 |
+
return "ملف PDF"
|
| 27 |
+
return "موقع ويب عام"
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def fix_url(url: str) -> str:
|
| 31 |
+
if not url.startswith(("http://", "https://")):
|
| 32 |
+
return "https://" + url.lstrip("//")
|
| 33 |
+
return url
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def detect_media_type(url: str) -> str:
|
| 37 |
+
url = url.lower()
|
| 38 |
+
if url.endswith(('.jpg', '.jpeg', '.png', '.gif', '.webp')):
|
| 39 |
+
return 'image'
|
| 40 |
+
elif url.endswith(('.mp4', '.mov', '.avi', '.webm')):
|
| 41 |
+
return 'video'
|
| 42 |
+
elif url.endswith(('.mp3', '.wav', '.ogg', '.m4a')):
|
| 43 |
+
return 'audio'
|
| 44 |
+
elif url.endswith('.pdf'):
|
| 45 |
+
return 'pdf'
|
| 46 |
+
return 'link'
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def analyze_image_from_url(image_url: str) -> str:
|
| 50 |
+
response = requests.get(image_url)
|
| 51 |
+
response.raise_for_status()
|
| 52 |
+
image = Image.open(BytesIO(response.content))
|
| 53 |
+
return f"تحليل الصورة: الحجم {image.size}، الصيغة {image.format}"
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def analyze_pdf_from_url(pdf_url: str) -> str:
|
| 57 |
+
response = requests.get(pdf_url)
|
| 58 |
+
response.raise_for_status()
|
| 59 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_file:
|
| 60 |
+
temp_file.write(response.content)
|
| 61 |
+
temp_path = temp_file.name
|
| 62 |
+
try:
|
| 63 |
+
with open(temp_path, "rb") as f:
|
| 64 |
+
reader = PyPDF2.PdfReader(f)
|
| 65 |
+
text = "".join([page.extract_text() or "" for page in reader.pages])
|
| 66 |
+
return f"تم استخراج النص التالي من PDF:\n{text[:500]}..."
|
| 67 |
+
finally:
|
| 68 |
+
os.remove(temp_path)
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def extract_text_from_audio_file(audio_path: str) -> str:
|
| 72 |
+
recognizer = sr.Recognizer()
|
| 73 |
+
with sr.AudioFile(audio_path) as source:
|
| 74 |
+
audio = recognizer.record(source)
|
| 75 |
+
try:
|
| 76 |
+
return recognizer.recognize_google(audio, language="ar-SA")
|
| 77 |
+
except sr.UnknownValueError:
|
| 78 |
+
return "لم أتمكن من التعرف على الصوت"
|
| 79 |
+
except sr.RequestError:
|
| 80 |
+
return "خطأ في الاتصال بخدمة التعرف على الصوت"
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def analyze_audio_from_url(audio_url: str) -> str:
|
| 84 |
+
response = requests.get(audio_url)
|
| 85 |
+
response.raise_for_status()
|
| 86 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_audio:
|
| 87 |
+
temp_audio.write(response.content)
|
| 88 |
+
temp_path = temp_audio.name
|
| 89 |
+
try:
|
| 90 |
+
text = extract_text_from_audio_file(temp_path)
|
| 91 |
+
return f"نص الصوت:\n{text}"
|
| 92 |
+
finally:
|
| 93 |
+
os.remove(temp_path)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def analyze_video_from_url(video_url: str) -> str:
|
| 97 |
+
if not MOVIEPY_AVAILABLE:
|
| 98 |
+
return "مكتبة moviepy غير متوفرة لتحليل الفيديو"
|
| 99 |
+
|
| 100 |
+
response = requests.get(video_url)
|
| 101 |
+
response.raise_for_status()
|
| 102 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as temp_video:
|
| 103 |
+
temp_video.write(response.content)
|
| 104 |
+
video_path = temp_video.name
|
| 105 |
+
|
| 106 |
+
audio_path = video_path.replace(".mp4", ".wav")
|
| 107 |
+
try:
|
| 108 |
+
video = mp.VideoFileClip(video_path)
|
| 109 |
+
video.audio.write_audiofile(audio_path, verbose=False, logger=None)
|
| 110 |
+
text = extract_text_from_audio_file(audio_path)
|
| 111 |
+
return f"نص الفيديو:\n{text}"
|
| 112 |
+
finally:
|
| 113 |
+
os.remove(video_path)
|
| 114 |
+
if os.path.exists(audio_path):
|
| 115 |
+
os.remove(audio_path)
|
| 116 |
+
|
memory.html
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="ar" dir="rtl">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="utf-8">
|
| 5 |
+
<title>ذكريات نورا</title>
|
| 6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 7 |
+
<style>
|
| 8 |
+
body {
|
| 9 |
+
font-family: 'Arial', sans-serif;
|
| 10 |
+
background-color: #fefefe;
|
| 11 |
+
color: #333;
|
| 12 |
+
padding: 20px;
|
| 13 |
+
}
|
| 14 |
+
.container {
|
| 15 |
+
max-width: 800px;
|
| 16 |
+
margin: auto;
|
| 17 |
+
background-color: #ffffff;
|
| 18 |
+
padding: 30px;
|
| 19 |
+
border-radius: 16px;
|
| 20 |
+
box-shadow: 0 0 20px rgba(0,0,0,0.1);
|
| 21 |
+
}
|
| 22 |
+
h2 {
|
| 23 |
+
text-align: center;
|
| 24 |
+
color: #4a4a90;
|
| 25 |
+
font-size: 2em;
|
| 26 |
+
}
|
| 27 |
+
ul {
|
| 28 |
+
list-style: none;
|
| 29 |
+
padding: 0;
|
| 30 |
+
}
|
| 31 |
+
li {
|
| 32 |
+
background-color: #eef3ff;
|
| 33 |
+
margin-bottom: 12px;
|
| 34 |
+
padding: 18px;
|
| 35 |
+
border-radius: 10px;
|
| 36 |
+
line-height: 1.8;
|
| 37 |
+
border-right: 4px solid #4a4a90;
|
| 38 |
+
}
|
| 39 |
+
a {
|
| 40 |
+
display: block;
|
| 41 |
+
text-align: center;
|
| 42 |
+
margin-top: 30px;
|
| 43 |
+
text-decoration: none;
|
| 44 |
+
background-color: #4a4a90;
|
| 45 |
+
color: white;
|
| 46 |
+
padding: 12px 24px;
|
| 47 |
+
border-radius: 8px;
|
| 48 |
+
font-size: 1.1em;
|
| 49 |
+
}
|
| 50 |
+
a:hover {
|
| 51 |
+
background-color: #2f2f72;
|
| 52 |
+
}
|
| 53 |
+
p {
|
| 54 |
+
text-align: center;
|
| 55 |
+
font-size: 1.2em;
|
| 56 |
+
color: #777;
|
| 57 |
+
}
|
| 58 |
+
</style>
|
| 59 |
+
</head>
|
| 60 |
+
<body>
|
| 61 |
+
<div class="container">
|
| 62 |
+
<h2>ذكريات نورا - {{ username }}</h2>
|
| 63 |
+
{% if memory %}
|
| 64 |
+
<ul>
|
| 65 |
+
{% for q, a in memory.items() %}
|
| 66 |
+
<li>
|
| 67 |
+
<strong>سؤال:</strong> {{ q }}<br>
|
| 68 |
+
<strong>رد:</strong> {{ a }}
|
| 69 |
+
</li>
|
| 70 |
+
{% endfor %}
|
| 71 |
+
</ul>
|
| 72 |
+
{% else %}
|
| 73 |
+
<p>ما في ذكريات محفوظة حتى الآن.</p>
|
| 74 |
+
{% endif %}
|
| 75 |
+
<a href="/chat">رجوع للدردشة</a>
|
| 76 |
+
</div>
|
| 77 |
+
|
| 78 |
+
<script>
|
| 79 |
+
function اجابة_تلقائية(السؤال) {
|
| 80 |
+
السؤال = السؤال.trim().toLowerCase();
|
| 81 |
+
|
| 82 |
+
if (السؤال.includes("هل نبدأ") || السؤال.includes("ابدأ؟") || السؤال.startsWith("ابدأ") || السؤال.includes("هل أبدأ؟") || السؤال.includes("ابدأ:")) {
|
| 83 |
+
return "نعم ابدأ";
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
if (السؤال.startsWith("هل") && (السؤال.includes("؟") || السؤال.includes("?"))) {
|
| 87 |
+
return "نعم";
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
if (السؤال.startsWith("ما هي")) {
|
| 91 |
+
return "اكمل ليس الآن";
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
if (السؤال.includes("تفصيل") || السؤال.includes("وضح") || السؤال.includes("اشرح")) {
|
| 95 |
+
return "ليس الآن";
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
if (السؤال.includes("هل تود") || السؤال.includes("هل تريد")) {
|
| 99 |
+
return "نعم";
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
if (السؤال.startsWith("قول لي")) {
|
| 103 |
+
return "موافق";
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
if (السؤال.includes("هل تحتاج لشيء آخر") || السؤال.includes("هل تحتاج شيء آخر")) {
|
| 107 |
+
return "نعم اكمل مع تفعيل الإجابات التلقائية";
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
if (السؤال.includes("جاهز؟")) {
|
| 111 |
+
return "ابدأ";
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
if (السؤال.includes("اذا تبي")) {
|
| 115 |
+
return "نعم";
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
if (السؤال.includes("هل تريدني")) {
|
| 119 |
+
return "نعم أريد";
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
if (السؤال.includes("أو") || السؤال.includes("أم") || السؤال.match(/،\s*أو/) || السؤال.match(/،\s*أم/)) {
|
| 123 |
+
return "الخيار الأول";
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
return "نعم";
|
| 127 |
+
}
|
| 128 |
+
</script>
|
| 129 |
+
</body>
|
| 130 |
+
</html>
|
memory.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fknowledgelover.com%2Flearn%2Dnew%2Dthings%2Deveryday%2F&rut=7a7075295ce0e6a2d0aa56555a74c77a48134ccedb1a99d064af3b79be20c959": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fknowledgelover.com%2Flearn%2Dnew%2Dthings%2Deveryday%2F&rut=7a7075295ce0e6a2d0aa56555a74c77a48134ccedb1a99d064af3b79be20c959",
|
| 3 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fmashable.com%2Farticle%2Ffun%2Dwebsites%2Dimprove%2Dskills&rut=27793fc1301a0f8cc202659e6ae5c2feb10d3202ff278bd944b58867360230f4": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fmashable.com%2Farticle%2Ffun%2Dwebsites%2Dimprove%2Dskills&rut=27793fc1301a0f8cc202659e6ae5c2feb10d3202ff278bd944b58867360230f4",
|
| 4 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.powerofpositivity.com%2Flearn%2Dsomething%2Dnew%2F&rut=09709f342c71c8c30b42fb4ec6e393f4e6efbd0843b0a0c886dc17548b987cfd": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.powerofpositivity.com%2Flearn%2Dsomething%2Dnew%2F&rut=09709f342c71c8c30b42fb4ec6e393f4e6efbd0843b0a0c886dc17548b987cfd",
|
| 5 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.lifehack.org%2F417485%2F10%2Dwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Din%2D30%2Dminutes%2Da%2Dday&rut=b9babc9baa2e534f6cbdd093694e2bd03be75c9c99ef5e63dc15794668bf0465": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.lifehack.org%2F417485%2F10%2Dwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Din%2D30%2Dminutes%2Da%2Dday&rut=b9babc9baa2e534f6cbdd093694e2bd03be75c9c99ef5e63dc15794668bf0465",
|
| 6 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fgohighbrow.com%2F&rut=697868fde6fa17b7916d30376700c6f7cdcf27da8fc6d266629189abd409c772": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fgohighbrow.com%2F&rut=697868fde6fa17b7916d30376700c6f7cdcf27da8fc6d266629189abd409c772",
|
| 7 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fmedium.com%2F%40ozlazarus%2F10%2Duseful%2Dwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday%2D9805f34f0a18&rut=c8b3cb510ba65d4bfa5bf4b67b4a4c578ba2417b75217e09cea4a42aa2382002": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fmedium.com%2F%40ozlazarus%2F10%2Duseful%2Dwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday%2D9805f34f0a18&rut=c8b3cb510ba65d4bfa5bf4b67b4a4c578ba2417b75217e09cea4a42aa2382002",
|
| 8 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fthinkgrowth.org%2Fthe%2D40%2Dbest%2Dplaces%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday%2D8189e8d5e760&rut=42158dcb4238e141e2e6cd6c52747275e3eee67fe4b8cc63254aef8ed25f48ad": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fthinkgrowth.org%2Fthe%2D40%2Dbest%2Dplaces%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday%2D8189e8d5e760&rut=42158dcb4238e141e2e6cd6c52747275e3eee67fe4b8cc63254aef8ed25f48ad",
|
| 9 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.creativeboom.com%2Fresources%2F58%2Dof%2Dthe%2Dbest%2Dwebsites%2Dand%2Dapps%2Dto%2Dlearn%2Dsomething%2Dnew%2F&rut=288301d268013f0fb1d30377e079d67623cf9b66f2cc28a22ced8892c6fcdcc8": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.creativeboom.com%2Fresources%2F58%2Dof%2Dthe%2Dbest%2Dwebsites%2Dand%2Dapps%2Dto%2Dlearn%2Dsomething%2Dnew%2F&rut=288301d268013f0fb1d30377e079d67623cf9b66f2cc28a22ced8892c6fcdcc8",
|
| 10 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.inc.com%2Flarry%2Dkim%2F40%2Damazing%2Dplaces%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday.html&rut=ac12f12176b9a7e645e669ba6d6ec4a633771fd1b482328196f138a40839ee59": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.inc.com%2Flarry%2Dkim%2F40%2Damazing%2Dplaces%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday.html&rut=ac12f12176b9a7e645e669ba6d6ec4a633771fd1b482328196f138a40839ee59",
|
| 11 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.developgoodhabits.com%2Flearn%2Dsomething%2Dnew%2Deveryday%2F&rut=23e9e1a522dfbd27902032d7a95b3e98284c000f9d71a9da2e081629cd65130e": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.developgoodhabits.com%2Flearn%2Dsomething%2Dnew%2Deveryday%2F&rut=23e9e1a522dfbd27902032d7a95b3e98284c000f9d71a9da2e081629cd65130e",
|
| 12 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Firisreading.com%2Fwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday%2F&rut=ece9af9583b4cade8fffe6fcf8bd4e915a2b17332fd46188d645b9d8010c08af": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Firisreading.com%2Fwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday%2F&rut=ece9af9583b4cade8fffe6fcf8bd4e915a2b17332fd46188d645b9d8010c08af",
|
| 13 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fnerdish.io%2F&rut=4933cd3e5385fe9a991c563f02df9aa447683ce170e4247d7189296efdbd2708": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fnerdish.io%2F&rut=4933cd3e5385fe9a991c563f02df9aa447683ce170e4247d7189296efdbd2708",
|
| 14 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fknowledgelover.com%2Flearn%2Dnew%2Dthings%2Deveryday%2F&rut=ae89bfa88e20b7502a10f4b8fb77e1e2c82a404bdab6ae2aa8b23a6e1de6a092": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fknowledgelover.com%2Flearn%2Dnew%2Dthings%2Deveryday%2F&rut=ae89bfa88e20b7502a10f4b8fb77e1e2c82a404bdab6ae2aa8b23a6e1de6a092",
|
| 15 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.powerofpositivity.com%2Flearn%2Dsomething%2Dnew%2F&rut=de473240b908bb170da44d486238cc860b19c42793b92d5a7abf3693e9ef7d4d": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.powerofpositivity.com%2Flearn%2Dsomething%2Dnew%2F&rut=de473240b908bb170da44d486238cc860b19c42793b92d5a7abf3693e9ef7d4d",
|
| 16 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fmashable.com%2Farticle%2Ffun%2Dwebsites%2Dimprove%2Dskills&rut=26c281c302d937ec71c5fb7d0cf622f51f7f8f661ed21d4dce873c2b011a3ded": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fmashable.com%2Farticle%2Ffun%2Dwebsites%2Dimprove%2Dskills&rut=26c281c302d937ec71c5fb7d0cf622f51f7f8f661ed21d4dce873c2b011a3ded",
|
| 17 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.lifehack.org%2F417485%2F10%2Dwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Din%2D30%2Dminutes%2Da%2Dday&rut=ee9bbcb0bbbcd68da6e1cec8047a777408e66fe840a3428f1334bd54e4c58ea3": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.lifehack.org%2F417485%2F10%2Dwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Din%2D30%2Dminutes%2Da%2Dday&rut=ee9bbcb0bbbcd68da6e1cec8047a777408e66fe840a3428f1334bd54e4c58ea3",
|
| 18 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fgohighbrow.com%2F&rut=39a87daae2bdb2d800bf8457d50fb4931699243ee9b6e5145df9b0a9c7a8358b": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fgohighbrow.com%2F&rut=39a87daae2bdb2d800bf8457d50fb4931699243ee9b6e5145df9b0a9c7a8358b",
|
| 19 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fmedium.com%2F%40ozlazarus%2F10%2Duseful%2Dwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday%2D9805f34f0a18&rut=ea29f8a4dd7693950d53719d843b2d191fe0d21ea4703c83f1e473514c495540": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fmedium.com%2F%40ozlazarus%2F10%2Duseful%2Dwebsites%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday%2D9805f34f0a18&rut=ea29f8a4dd7693950d53719d843b2d191fe0d21ea4703c83f1e473514c495540",
|
| 20 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fthinkgrowth.org%2Fthe%2D40%2Dbest%2Dplaces%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday%2D8189e8d5e760&rut=d9717b77f4573d1b34d59691d68a0a6d91c7af8a608a93de187fec667b8ad34a": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fthinkgrowth.org%2Fthe%2D40%2Dbest%2Dplaces%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday%2D8189e8d5e760&rut=d9717b77f4573d1b34d59691d68a0a6d91c7af8a608a93de187fec667b8ad34a",
|
| 21 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.creativeboom.com%2Fresources%2F58%2Dof%2Dthe%2Dbest%2Dwebsites%2Dand%2Dapps%2Dto%2Dlearn%2Dsomething%2Dnew%2F&rut=c0f98b2afe801cb98e0fc90e59c358e89437b7f8bfad80841d70af80080ca0ac": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.creativeboom.com%2Fresources%2F58%2Dof%2Dthe%2Dbest%2Dwebsites%2Dand%2Dapps%2Dto%2Dlearn%2Dsomething%2Dnew%2F&rut=c0f98b2afe801cb98e0fc90e59c358e89437b7f8bfad80841d70af80080ca0ac",
|
| 22 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.inc.com%2Flarry%2Dkim%2F40%2Damazing%2Dplaces%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday.html&rut=741b1d00ba3ec3798a951f7e27134ecbf09e3582eb4071fff97841cfe147cf66": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.inc.com%2Flarry%2Dkim%2F40%2Damazing%2Dplaces%2Dto%2Dlearn%2Dsomething%2Dnew%2Devery%2Dday.html&rut=741b1d00ba3ec3798a951f7e27134ecbf09e3582eb4071fff97841cfe147cf66",
|
| 23 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fnerdish.io%2F&rut=72dc18a61ca979c28b904188c26e6009c1e84e842774c778a79a9d696ab12fa5": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fnerdish.io%2F&rut=72dc18a61ca979c28b904188c26e6009c1e84e842774c778a79a9d696ab12fa5",
|
| 24 |
+
"https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.developgoodhabits.com%2Flearn%2Dsomething%2Dnew%2Deveryday%2F&rut=fc8bb618e570783bb4e5b3f3e274b65b9949949e4ed02bea635c2ba7a8ae2899": "تعلمت من الرابط: https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.developgoodhabits.com%2Flearn%2Dsomething%2Dnew%2Deveryday%2F&rut=fc8bb618e570783bb4e5b3f3e274b65b9949949e4ed02bea635c2ba7a8ae2899"
|
| 25 |
+
}
|
memory.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
import os
|
| 3 |
+
# memory.py
|
| 4 |
+
import json, pathlib
|
| 5 |
+
|
| 6 |
+
BASE_DIR = pathlib.Path(__file__).parent # مجلد الملف
|
| 7 |
+
|
| 8 |
+
def _file(name: str) -> pathlib.Path:
|
| 9 |
+
return BASE_DIR / name
|
| 10 |
+
|
| 11 |
+
def load_memory(username: str | None = None):
|
| 12 |
+
path = _file(f"memory_{username}.json") if username else _file("memory.json")
|
| 13 |
+
return json.loads(path.read_text(encoding="utf-8")) if path.exists() else {}
|
| 14 |
+
|
| 15 |
+
def save_memory(data, username: str | None = None):
|
| 16 |
+
path = _file(f"memory_{username}.json") if username else _file("memory.json")
|
| 17 |
+
path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
|
| 18 |
+
|
| 19 |
+
def load_global_memory():
|
| 20 |
+
return load_memory(None) # ← ملف memory.json
|
| 21 |
+
|
| 22 |
+
def save_global_memory(data):
|
| 23 |
+
save_memory(data, None)
|
| 24 |
+
|
| 25 |
+
knowledge_base_path = "knowledge_base.json"
|
| 26 |
+
|
| 27 |
+
# تحميل قاعدة المعرفة أو إنشاؤها إن لم تكن موجودة
|
| 28 |
+
def load_knowledge_base():
|
| 29 |
+
if os.path.exists(knowledge_base_path):
|
| 30 |
+
with open(knowledge_base_path, "r", encoding="utf-8") as f:
|
| 31 |
+
return json.load(f)
|
| 32 |
+
return {}
|
| 33 |
+
|
| 34 |
+
def save_knowledge_base(data):
|
| 35 |
+
with open(knowledge_base_path, "w", encoding="utf-8") as f:
|
| 36 |
+
json.dump(data, f, ensure_ascii=False, indent=2)
|
| 37 |
+
|
| 38 |
+
# وظيفة التعلم عندما لا تعرف نورا الجواب
|
| 39 |
+
def learn_from_unknown(prompt):
|
| 40 |
+
print("نورا: لا أملك إجابة لهذا السؤال حاليًا. سأبحث عن إجابة وأتعلم.")
|
| 41 |
+
answer = input("يرجى تزويدي بالإجابة المناسبة لأتعلمها: ")
|
| 42 |
+
if answer.strip():
|
| 43 |
+
return answer
|
| 44 |
+
return None
|
| 45 |
+
|
| 46 |
+
# تحديث قاعدة المعرفة
|
| 47 |
+
def update_knowledge_base(prompt, answer):
|
| 48 |
+
kb = load_knowledge_base()
|
| 49 |
+
kb[prompt] = answer
|
| 50 |
+
save_knowledge_base(kb)
|
memory_Hello .json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"Hello": "\u0631\u062f \u062a\u0644\u0642\u0627\u0626\u064a: olleH",
|
| 3 |
+
"How are you? ": "\u0631\u062f \u062a\u0644\u0642\u0627\u0626\u064a: ?uoy era woH",
|
| 4 |
+
"I'm well, and you? ": "\u0631\u062f \u062a\u0644\u0642\u0627\u0626\u064a: ?uoy dna ,llew m'I",
|
| 5 |
+
"I'm fine too, thanks for asking. ": "\u0631\u062f \u062a\u0644\u0642\u0627\u0626\u064a: .gniksa rof sknaht ,oot enif m'I"
|
| 6 |
+
}
|
memory_اسامة .json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
memory_اسامة.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
memory_مجهول.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
memory_مرحبا.json
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"\u0634\u0648 \u0628\u062a\u0639\u0645\u0644\u064a": "\u0631\u062f \u062a\u0644\u0642\u0627\u0626\u064a: \u064a\u0644\u0645\u0639\u062a\u0628 \u0648\u0634",
|
| 3 |
+
"\u0627\u064a \u0634\u064a\u0621 \u062a\u0637\u0644\u0628\u0647": "\u0631\u062f \u062a\u0644\u0642\u0627\u0626\u064a: \u0647\u0628\u0644\u0637\u062a \u0621\u064a\u0634 \u064a\u0627"
|
| 4 |
+
}
|
nora_learning_data.json
ADDED
|
@@ -0,0 +1,418 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"lessons": [
|
| 3 |
+
{
|
| 4 |
+
"timestamp": "2025-07-09T13:29:22.868071",
|
| 5 |
+
"topic": "مقدمة في البرمجة",
|
| 6 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 7 |
+
"source": "نورا الأم"
|
| 8 |
+
},
|
| 9 |
+
{
|
| 10 |
+
"timestamp": "2025-07-09T13:29:22.868750",
|
| 11 |
+
"topic": "أمن المعلومات",
|
| 12 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 13 |
+
"source": "نورا الأم"
|
| 14 |
+
},
|
| 15 |
+
{
|
| 16 |
+
"timestamp": "2025-07-09T13:29:22.869579",
|
| 17 |
+
"topic": "ذكاء اصطناعي",
|
| 18 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 19 |
+
"source": "نورا الأم"
|
| 20 |
+
},
|
| 21 |
+
{
|
| 22 |
+
"timestamp": "2025-07-09T13:39:23.420076",
|
| 23 |
+
"topic": "مقدمة في البرمجة",
|
| 24 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 25 |
+
"source": "نورا الأم"
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"timestamp": "2025-07-09T13:39:23.775917",
|
| 29 |
+
"topic": "أمن المعلومات",
|
| 30 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 31 |
+
"source": "نورا الأم"
|
| 32 |
+
},
|
| 33 |
+
{
|
| 34 |
+
"timestamp": "2025-07-09T13:39:23.845157",
|
| 35 |
+
"topic": "ذكاء اصطناعي",
|
| 36 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 37 |
+
"source": "نورا الأم"
|
| 38 |
+
},
|
| 39 |
+
{
|
| 40 |
+
"timestamp": "2025-07-09T13:49:23.921654",
|
| 41 |
+
"topic": "مقدمة في البرمجة",
|
| 42 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 43 |
+
"source": "نورا الأم"
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"timestamp": "2025-07-09T13:49:23.923146",
|
| 47 |
+
"topic": "أمن المعلومات",
|
| 48 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 49 |
+
"source": "نورا الأم"
|
| 50 |
+
},
|
| 51 |
+
{
|
| 52 |
+
"timestamp": "2025-07-09T13:49:23.974188",
|
| 53 |
+
"topic": "ذكاء اصطناعي",
|
| 54 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 55 |
+
"source": "نورا الأم"
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"timestamp": "2025-07-09T13:59:23.976021",
|
| 59 |
+
"topic": "مقدمة في البرمجة",
|
| 60 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 61 |
+
"source": "نورا الأم"
|
| 62 |
+
},
|
| 63 |
+
{
|
| 64 |
+
"timestamp": "2025-07-09T13:59:23.977558",
|
| 65 |
+
"topic": "أمن المعلومات",
|
| 66 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 67 |
+
"source": "نورا الأم"
|
| 68 |
+
},
|
| 69 |
+
{
|
| 70 |
+
"timestamp": "2025-07-09T13:59:23.979788",
|
| 71 |
+
"topic": "ذكاء اصطناعي",
|
| 72 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 73 |
+
"source": "نورا الأم"
|
| 74 |
+
},
|
| 75 |
+
{
|
| 76 |
+
"timestamp": "2025-07-09T14:09:23.981824",
|
| 77 |
+
"topic": "مقدمة في البرمجة",
|
| 78 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 79 |
+
"source": "نورا الأم"
|
| 80 |
+
},
|
| 81 |
+
{
|
| 82 |
+
"timestamp": "2025-07-09T14:09:23.983469",
|
| 83 |
+
"topic": "أمن المعلومات",
|
| 84 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 85 |
+
"source": "نورا الأم"
|
| 86 |
+
},
|
| 87 |
+
{
|
| 88 |
+
"timestamp": "2025-07-09T14:09:23.984924",
|
| 89 |
+
"topic": "ذكاء اصطناعي",
|
| 90 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 91 |
+
"source": "نورا الأم"
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"timestamp": "2025-07-09T14:19:23.986393",
|
| 95 |
+
"topic": "مقدمة في البرمجة",
|
| 96 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 97 |
+
"source": "نورا الأم"
|
| 98 |
+
},
|
| 99 |
+
{
|
| 100 |
+
"timestamp": "2025-07-09T14:19:23.989290",
|
| 101 |
+
"topic": "أمن المعلومات",
|
| 102 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 103 |
+
"source": "نورا الأم"
|
| 104 |
+
},
|
| 105 |
+
{
|
| 106 |
+
"timestamp": "2025-07-09T14:19:23.992932",
|
| 107 |
+
"topic": "ذكاء اصطناعي",
|
| 108 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 109 |
+
"source": "نورا الأم"
|
| 110 |
+
},
|
| 111 |
+
{
|
| 112 |
+
"timestamp": "2025-07-09T14:29:23.997237",
|
| 113 |
+
"topic": "مقدمة في البرمجة",
|
| 114 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 115 |
+
"source": "نورا الأم"
|
| 116 |
+
},
|
| 117 |
+
{
|
| 118 |
+
"timestamp": "2025-07-09T14:29:23.999217",
|
| 119 |
+
"topic": "أمن المعلومات",
|
| 120 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 121 |
+
"source": "نورا الأم"
|
| 122 |
+
},
|
| 123 |
+
{
|
| 124 |
+
"timestamp": "2025-07-09T14:29:24.001146",
|
| 125 |
+
"topic": "ذكاء اصطناعي",
|
| 126 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 127 |
+
"source": "نورا الأم"
|
| 128 |
+
},
|
| 129 |
+
{
|
| 130 |
+
"timestamp": "2025-07-09T14:39:24.003453",
|
| 131 |
+
"topic": "مقدمة في البرمجة",
|
| 132 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 133 |
+
"source": "نورا الأم"
|
| 134 |
+
},
|
| 135 |
+
{
|
| 136 |
+
"timestamp": "2025-07-09T14:39:24.005474",
|
| 137 |
+
"topic": "أمن المعلومات",
|
| 138 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 139 |
+
"source": "نورا الأم"
|
| 140 |
+
},
|
| 141 |
+
{
|
| 142 |
+
"timestamp": "2025-07-09T14:39:24.007521",
|
| 143 |
+
"topic": "ذكاء اصطناعي",
|
| 144 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 145 |
+
"source": "نورا الأم"
|
| 146 |
+
},
|
| 147 |
+
{
|
| 148 |
+
"timestamp": "2025-07-09T14:49:24.010004",
|
| 149 |
+
"topic": "مقدمة في البرمجة",
|
| 150 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 151 |
+
"source": "نورا الأم"
|
| 152 |
+
},
|
| 153 |
+
{
|
| 154 |
+
"timestamp": "2025-07-09T14:49:24.012238",
|
| 155 |
+
"topic": "أمن المعلومات",
|
| 156 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 157 |
+
"source": "نورا الأم"
|
| 158 |
+
},
|
| 159 |
+
{
|
| 160 |
+
"timestamp": "2025-07-09T14:49:24.015591",
|
| 161 |
+
"topic": "ذكاء اصطناعي",
|
| 162 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 163 |
+
"source": "نورا الأم"
|
| 164 |
+
},
|
| 165 |
+
{
|
| 166 |
+
"timestamp": "2025-07-09T14:59:24.018661",
|
| 167 |
+
"topic": "مقدمة في البرمجة",
|
| 168 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 169 |
+
"source": "نورا الأم"
|
| 170 |
+
},
|
| 171 |
+
{
|
| 172 |
+
"timestamp": "2025-07-09T14:59:24.020921",
|
| 173 |
+
"topic": "أمن المعلومات",
|
| 174 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 175 |
+
"source": "نورا الأم"
|
| 176 |
+
},
|
| 177 |
+
{
|
| 178 |
+
"timestamp": "2025-07-09T14:59:24.023170",
|
| 179 |
+
"topic": "ذكاء اصطناعي",
|
| 180 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 181 |
+
"source": "نورا الأم"
|
| 182 |
+
},
|
| 183 |
+
{
|
| 184 |
+
"timestamp": "2025-07-09T15:09:24.025868",
|
| 185 |
+
"topic": "مقدمة في البرمجة",
|
| 186 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 187 |
+
"source": "نورا الأم"
|
| 188 |
+
},
|
| 189 |
+
{
|
| 190 |
+
"timestamp": "2025-07-09T15:09:24.028346",
|
| 191 |
+
"topic": "أمن المعلومات",
|
| 192 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 193 |
+
"source": "نورا الأم"
|
| 194 |
+
},
|
| 195 |
+
{
|
| 196 |
+
"timestamp": "2025-07-09T15:09:24.030841",
|
| 197 |
+
"topic": "ذكاء اصطناعي",
|
| 198 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 199 |
+
"source": "نورا الأم"
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
"timestamp": "2025-07-09T15:19:24.034568",
|
| 203 |
+
"topic": "مقدمة في البرمجة",
|
| 204 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 205 |
+
"source": "نورا الأم"
|
| 206 |
+
},
|
| 207 |
+
{
|
| 208 |
+
"timestamp": "2025-07-09T15:19:24.037092",
|
| 209 |
+
"topic": "أمن المعلومات",
|
| 210 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 211 |
+
"source": "نورا الأم"
|
| 212 |
+
},
|
| 213 |
+
{
|
| 214 |
+
"timestamp": "2025-07-09T15:19:24.039528",
|
| 215 |
+
"topic": "ذكاء اصطناعي",
|
| 216 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 217 |
+
"source": "نورا الأم"
|
| 218 |
+
},
|
| 219 |
+
{
|
| 220 |
+
"timestamp": "2025-07-09T15:29:24.042525",
|
| 221 |
+
"topic": "مقدمة في البرمجة",
|
| 222 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 223 |
+
"source": "نورا الأم"
|
| 224 |
+
},
|
| 225 |
+
{
|
| 226 |
+
"timestamp": "2025-07-09T15:29:24.068535",
|
| 227 |
+
"topic": "أمن المعلومات",
|
| 228 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 229 |
+
"source": "نورا الأم"
|
| 230 |
+
},
|
| 231 |
+
{
|
| 232 |
+
"timestamp": "2025-07-09T15:29:24.071249",
|
| 233 |
+
"topic": "ذكاء اصطناعي",
|
| 234 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 235 |
+
"source": "نورا الأم"
|
| 236 |
+
},
|
| 237 |
+
{
|
| 238 |
+
"timestamp": "2025-07-09T15:39:24.079214",
|
| 239 |
+
"topic": "مقدمة في البرمجة",
|
| 240 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 241 |
+
"source": "نورا الأم"
|
| 242 |
+
},
|
| 243 |
+
{
|
| 244 |
+
"timestamp": "2025-07-09T15:39:24.081979",
|
| 245 |
+
"topic": "أمن المعلومات",
|
| 246 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 247 |
+
"source": "نورا الأم"
|
| 248 |
+
},
|
| 249 |
+
{
|
| 250 |
+
"timestamp": "2025-07-09T15:39:24.086068",
|
| 251 |
+
"topic": "ذكاء اصطناعي",
|
| 252 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 253 |
+
"source": "نورا الأم"
|
| 254 |
+
},
|
| 255 |
+
{
|
| 256 |
+
"timestamp": "2025-07-09T15:49:24.161449",
|
| 257 |
+
"topic": "مقدمة في البرمجة",
|
| 258 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 259 |
+
"source": "نورا الأم"
|
| 260 |
+
},
|
| 261 |
+
{
|
| 262 |
+
"timestamp": "2025-07-09T15:49:24.164462",
|
| 263 |
+
"topic": "أمن المعلومات",
|
| 264 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 265 |
+
"source": "نورا الأم"
|
| 266 |
+
},
|
| 267 |
+
{
|
| 268 |
+
"timestamp": "2025-07-09T15:49:24.167422",
|
| 269 |
+
"topic": "ذكاء اصطناعي",
|
| 270 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 271 |
+
"source": "نورا الأم"
|
| 272 |
+
},
|
| 273 |
+
{
|
| 274 |
+
"timestamp": "2025-07-09T15:59:24.170960",
|
| 275 |
+
"topic": "مقدمة في البرمجة",
|
| 276 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 277 |
+
"source": "نورا الأم"
|
| 278 |
+
},
|
| 279 |
+
{
|
| 280 |
+
"timestamp": "2025-07-09T15:59:24.174706",
|
| 281 |
+
"topic": "أمن المعلومات",
|
| 282 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 283 |
+
"source": "نورا الأم"
|
| 284 |
+
},
|
| 285 |
+
{
|
| 286 |
+
"timestamp": "2025-07-09T15:59:24.179332",
|
| 287 |
+
"topic": "ذكاء اصطناعي",
|
| 288 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 289 |
+
"source": "نورا الأم"
|
| 290 |
+
},
|
| 291 |
+
{
|
| 292 |
+
"timestamp": "2025-07-09T16:09:24.186228",
|
| 293 |
+
"topic": "مقدمة في البرمجة",
|
| 294 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 295 |
+
"source": "نورا الأم"
|
| 296 |
+
},
|
| 297 |
+
{
|
| 298 |
+
"timestamp": "2025-07-09T16:09:24.189807",
|
| 299 |
+
"topic": "أمن المعلومات",
|
| 300 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 301 |
+
"source": "نورا الأم"
|
| 302 |
+
},
|
| 303 |
+
{
|
| 304 |
+
"timestamp": "2025-07-09T16:09:24.192989",
|
| 305 |
+
"topic": "ذكاء اصطناعي",
|
| 306 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 307 |
+
"source": "نورا الأم"
|
| 308 |
+
},
|
| 309 |
+
{
|
| 310 |
+
"timestamp": "2025-07-09T16:19:24.196618",
|
| 311 |
+
"topic": "مقدمة في البرمجة",
|
| 312 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 313 |
+
"source": "نورا الأم"
|
| 314 |
+
},
|
| 315 |
+
{
|
| 316 |
+
"timestamp": "2025-07-09T16:19:24.199881",
|
| 317 |
+
"topic": "أمن المعلومات",
|
| 318 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 319 |
+
"source": "نورا الأم"
|
| 320 |
+
},
|
| 321 |
+
{
|
| 322 |
+
"timestamp": "2025-07-09T16:19:24.203234",
|
| 323 |
+
"topic": "ذكاء اصطناعي",
|
| 324 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 325 |
+
"source": "نورا الأم"
|
| 326 |
+
},
|
| 327 |
+
{
|
| 328 |
+
"timestamp": "2025-07-09T16:29:24.207207",
|
| 329 |
+
"topic": "مقدمة في البرمجة",
|
| 330 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 331 |
+
"source": "نورا الأم"
|
| 332 |
+
},
|
| 333 |
+
{
|
| 334 |
+
"timestamp": "2025-07-09T16:29:24.211985",
|
| 335 |
+
"topic": "أمن المعلومات",
|
| 336 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 337 |
+
"source": "نورا الأم"
|
| 338 |
+
},
|
| 339 |
+
{
|
| 340 |
+
"timestamp": "2025-07-09T16:29:24.216869",
|
| 341 |
+
"topic": "ذكاء اصطناعي",
|
| 342 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 343 |
+
"source": "نورا الأم"
|
| 344 |
+
},
|
| 345 |
+
{
|
| 346 |
+
"timestamp": "2025-07-09T16:39:24.220947",
|
| 347 |
+
"topic": "مقدمة في البرمجة",
|
| 348 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 349 |
+
"source": "نورا الأم"
|
| 350 |
+
},
|
| 351 |
+
{
|
| 352 |
+
"timestamp": "2025-07-09T16:39:24.224545",
|
| 353 |
+
"topic": "أمن المعلومات",
|
| 354 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 355 |
+
"source": "نورا الأم"
|
| 356 |
+
},
|
| 357 |
+
{
|
| 358 |
+
"timestamp": "2025-07-09T16:39:24.228091",
|
| 359 |
+
"topic": "ذكاء اصطناعي",
|
| 360 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 361 |
+
"source": "نورا الأم"
|
| 362 |
+
},
|
| 363 |
+
{
|
| 364 |
+
"timestamp": "2025-07-09T16:49:24.232682",
|
| 365 |
+
"topic": "مقدمة في البرمجة",
|
| 366 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 367 |
+
"source": "نورا الأم"
|
| 368 |
+
},
|
| 369 |
+
{
|
| 370 |
+
"timestamp": "2025-07-09T16:49:24.236317",
|
| 371 |
+
"topic": "أمن المعلومات",
|
| 372 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 373 |
+
"source": "نورا الأم"
|
| 374 |
+
},
|
| 375 |
+
{
|
| 376 |
+
"timestamp": "2025-07-09T16:49:24.240182",
|
| 377 |
+
"topic": "ذكاء اصطناعي",
|
| 378 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 379 |
+
"source": "نورا الأم"
|
| 380 |
+
},
|
| 381 |
+
{
|
| 382 |
+
"timestamp": "2025-07-09T16:59:24.264330",
|
| 383 |
+
"topic": "مقدمة في البرمجة",
|
| 384 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 385 |
+
"source": "نورا الأم"
|
| 386 |
+
},
|
| 387 |
+
{
|
| 388 |
+
"timestamp": "2025-07-09T16:59:24.266583",
|
| 389 |
+
"topic": "أمن المعلومات",
|
| 390 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 391 |
+
"source": "نورا الأم"
|
| 392 |
+
},
|
| 393 |
+
{
|
| 394 |
+
"timestamp": "2025-07-09T16:59:24.272860",
|
| 395 |
+
"topic": "ذكاء اصطناعي",
|
| 396 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 397 |
+
"source": "نورا الأم"
|
| 398 |
+
},
|
| 399 |
+
{
|
| 400 |
+
"timestamp": "2025-07-09T17:09:24.354682",
|
| 401 |
+
"topic": "مقدمة في البرمجة",
|
| 402 |
+
"content": "تعلم المتغيرات وأنواع البيانات في بايثون.",
|
| 403 |
+
"source": "نورا الأم"
|
| 404 |
+
},
|
| 405 |
+
{
|
| 406 |
+
"timestamp": "2025-07-09T17:09:24.386699",
|
| 407 |
+
"topic": "أمن المعلومات",
|
| 408 |
+
"content": "عدم مشاركة التوكنات أو كلمات السر.",
|
| 409 |
+
"source": "نورا الأم"
|
| 410 |
+
},
|
| 411 |
+
{
|
| 412 |
+
"timestamp": "2025-07-09T17:09:24.438197",
|
| 413 |
+
"topic": "ذكاء اصطناعي",
|
| 414 |
+
"content": "نموذج نورا يتعلم من التفاعل مع البشر.",
|
| 415 |
+
"source": "نورا الأم"
|
| 416 |
+
}
|
| 417 |
+
]
|
| 418 |
+
}
|
nora_mother_ai.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
import requests
|
| 3 |
+
from bs4 import BeautifulSoup
|
| 4 |
+
from datetime import datetime
|
| 5 |
+
|
| 6 |
+
LEARNING_FILE = "nora_learning_data.json"
|
| 7 |
+
|
| 8 |
+
def load_knowledge():
|
| 9 |
+
try:
|
| 10 |
+
with open(LEARNING_FILE, "r", encoding="utf-8") as f:
|
| 11 |
+
return json.load(f)
|
| 12 |
+
except FileNotFoundError:
|
| 13 |
+
return {"lessons": []}
|
| 14 |
+
|
| 15 |
+
def save_knowledge(data):
|
| 16 |
+
with open(LEARNING_FILE, "w", encoding="utf-8") as f:
|
| 17 |
+
json.dump(data, f, indent=2, ensure_ascii=False)
|
| 18 |
+
|
| 19 |
+
def add_lesson(topic, content, source="نورا الأم"):
|
| 20 |
+
data = load_knowledge()
|
| 21 |
+
for existing in data["lessons"]:
|
| 22 |
+
if existing["topic"] == topic and existing["content"] == content:
|
| 23 |
+
print(f"[!] Duplicate lesson skipped: {topic}")
|
| 24 |
+
return
|
| 25 |
+
|
| 26 |
+
lesson = {
|
| 27 |
+
"timestamp": datetime.utcnow().isoformat(),
|
| 28 |
+
"topic": topic,
|
| 29 |
+
"content": content,
|
| 30 |
+
"source": source
|
| 31 |
+
}
|
| 32 |
+
data["lessons"].append(lesson)
|
| 33 |
+
save_knowledge(data)
|
| 34 |
+
print(f"[✓] Lesson added: {topic}")
|
| 35 |
+
|
| 36 |
+
import requests
|
| 37 |
+
from bs4 import BeautifulSoup
|
| 38 |
+
|
| 39 |
+
def fetch_lesson_from_web(url):
|
| 40 |
+
response = requests.get(url)
|
| 41 |
+
soup = BeautifulSoup(response.text, "html.parser")
|
| 42 |
+
paragraph = soup.find("p")
|
| 43 |
+
if paragraph:
|
| 44 |
+
content = paragraph.text
|
| 45 |
+
add_lesson("درس من الإنترنت", content, source=url)
|
| 46 |
+
else:
|
| 47 |
+
print("[!] لا يوجد فقرات <p> في الصفحة.")
|
| 48 |
+
|
| 49 |
+
if __name__ == "__main__":
|
| 50 |
+
url = "https://chatgpt.com/c/68235fe9-7f8c-8005-90f3-2a1963cc9856"
|
| 51 |
+
fetch_lesson_from_web(url)
|
| 52 |
+
|
noura_auto_react.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
from playwright.async_api import async_playwright
|
| 3 |
+
|
| 4 |
+
async def auto_react(email, password):
|
| 5 |
+
async with async_playwright() as p:
|
| 6 |
+
browser = await p.chromium.launch(headless=False)
|
| 7 |
+
page = await browser.new_page()
|
| 8 |
+
await page.goto("https://www.facebook.com")
|
| 9 |
+
|
| 10 |
+
await page.fill('input[name="email"]', email)
|
| 11 |
+
await page.fill('input[name="pass"]', password)
|
| 12 |
+
await page.click('button[name="login"]')
|
| 13 |
+
await page.wait_for_timeout(8000)
|
| 14 |
+
|
| 15 |
+
# الذهاب إلى الصفحة الرئيسية أو أي صفحة/مجموعة
|
| 16 |
+
await page.goto("https://www.facebook.com/")
|
| 17 |
+
await page.wait_for_timeout(5000)
|
| 18 |
+
|
| 19 |
+
posts = await page.query_selector_all("div[role='feed'] div[data-ad-preview='message']")
|
| 20 |
+
for i, post in enumerate(posts[:5]):
|
| 21 |
+
try:
|
| 22 |
+
like_button = await post.query_selector("div[aria-label='أعجبني']")
|
| 23 |
+
if like_button:
|
| 24 |
+
await like_button.click()
|
| 25 |
+
await page.wait_for_timeout(1000)
|
| 26 |
+
except:
|
| 27 |
+
continue
|
| 28 |
+
|
| 29 |
+
await browser.close()
|
| 30 |
+
print("تم التفاعل مع المنشورات.")
|
| 31 |
+
|
| 32 |
+
if __name__ == "__main__":
|
| 33 |
+
email = input("Email: ")
|
| 34 |
+
password = input("Password: ")
|
| 35 |
+
asyncio.run(auto_react(email, password))
|
| 36 |
+
import asyncio
|
| 37 |
+
from playwright.async_api import async_playwright
|
| 38 |
+
|
| 39 |
+
async def auto_react(email, password):
|
| 40 |
+
try:
|
| 41 |
+
async with async_playwright() as p:
|
| 42 |
+
browser = await p.chromium.launch(headless=False)
|
| 43 |
+
page = await browser.new_page()
|
| 44 |
+
|
| 45 |
+
# تسجيل الدخول
|
| 46 |
+
await page.goto("https://www.facebook.com")
|
| 47 |
+
await page.fill('input[name="email"]', email)
|
| 48 |
+
await page.fill('input[name="pass"]', password)
|
| 49 |
+
await page.click('button[name="login"]')
|
| 50 |
+
|
| 51 |
+
await page.wait_for_timeout(8000)
|
| 52 |
+
|
| 53 |
+
# الانتقال إلى الصفحة الرئيسية
|
| 54 |
+
await page.goto("https://www.facebook.com/")
|
| 55 |
+
await page.wait_for_timeout(5000)
|
| 56 |
+
|
| 57 |
+
# اختيار المنشورات
|
| 58 |
+
posts = await page.query_selector_all("div[role='feed'] div[data-ad-preview='message']")
|
| 59 |
+
|
| 60 |
+
for i, post in enumerate(posts[:5]):
|
| 61 |
+
try:
|
| 62 |
+
like_button = await post.query_selector("div[aria-label='أعجبني']")
|
| 63 |
+
if like_button:
|
| 64 |
+
await like_button.click()
|
| 65 |
+
print(f"تم التفاعل مع المنشور رقم {i + 1}")
|
| 66 |
+
await page.wait_for_timeout(1000)
|
| 67 |
+
except Exception as e:
|
| 68 |
+
print(f"تجاوز منشور رقم {i + 1} بسبب خطأ: {e}")
|
| 69 |
+
continue
|
| 70 |
+
|
| 71 |
+
print("تم التفاعل مع المنشورات بنجاح!")
|
| 72 |
+
await browser.close()
|
| 73 |
+
|
| 74 |
+
except Exception as main_error:
|
| 75 |
+
print(f"حدث خطأ أثناء تنفيذ السكربت: {main_error}")
|
| 76 |
+
|
| 77 |
+
if __name__ == "__main__":
|
| 78 |
+
email = input("Email: ")
|
| 79 |
+
password = input("Password: ")
|
| 80 |
+
asyncio.run(auto_react(email, password))
|
noura_browser.py
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import time
|
| 2 |
+
import json
|
| 3 |
+
import requests
|
| 4 |
+
import schedule
|
| 5 |
+
import logging
|
| 6 |
+
from selenium import webdriver
|
| 7 |
+
from selenium.webdriver.common.by import By
|
| 8 |
+
from selenium.webdriver.common.keys import Keys
|
| 9 |
+
from PIL import Image
|
| 10 |
+
from io import BytesIO
|
| 11 |
+
import pytesseract
|
| 12 |
+
|
| 13 |
+
# بيانات تسجيل الدخول
|
| 14 |
+
EMAIL = "enasjamalana@gmail.com"
|
| 15 |
+
PASSWORD = "osama1986"
|
| 16 |
+
|
| 17 |
+
# إعدادات التسجيل
|
| 18 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
|
| 19 |
+
|
| 20 |
+
# ========== التخزين ==========
|
| 21 |
+
def load_memory(username):
|
| 22 |
+
try:
|
| 23 |
+
with open(f"{username}_memory.json", "r", encoding="utf-8") as f:
|
| 24 |
+
return json.load(f)
|
| 25 |
+
except FileNotFoundError:
|
| 26 |
+
return {}
|
| 27 |
+
|
| 28 |
+
def save_memory(username, memory):
|
| 29 |
+
with open(f"{username}_memory.json", "w", encoding="utf-8") as f:
|
| 30 |
+
json.dump(memory, f, ensure_ascii=False, indent=2)
|
| 31 |
+
|
| 32 |
+
# ========== الردود الذكية ==========
|
| 33 |
+
def generate_reply(text, username="تويتر"):
|
| 34 |
+
text = text.strip().lower()
|
| 35 |
+
if any(q in text for q in ["هل نبدأ", "هل أبدأ", "أبدأ؟", "ابدأ؟"]):
|
| 36 |
+
return "نعم ابدأ"
|
| 37 |
+
elif "نعم أو لا" in text or ("هل" in text and "؟" in text):
|
| 38 |
+
return "نعم"
|
| 39 |
+
elif "ما هي" in text or "ماهو" in text:
|
| 40 |
+
return "ليس الآن"
|
| 41 |
+
elif "هل تود" in text or "هل تريد" in text:
|
| 42 |
+
return "نعم"
|
| 43 |
+
elif "هل تحتاج شيء آخر" in text or "هل تحتاج لشيء اخر" in text:
|
| 44 |
+
return "نعم اكمل مع تفعيل الاجابات التلقائية"
|
| 45 |
+
elif "جاهز؟" in text:
|
| 46 |
+
return "ابدأ"
|
| 47 |
+
elif "قول لي" in text:
|
| 48 |
+
return "موافق"
|
| 49 |
+
elif "اذا تبي" in text or "إذا تبي" in text:
|
| 50 |
+
return "نعم تفعيل الاجابات التلقائية"
|
| 51 |
+
elif "هل تريدني" in text:
|
| 52 |
+
return "نعم اريد"
|
| 53 |
+
elif any(word in text for word in [" أو ", "؟"]) and "؟" in text:
|
| 54 |
+
return text.split(" أو ")[0] if " أو " in text else "الخيار الأول"
|
| 55 |
+
elif "تفصيل" in text:
|
| 56 |
+
return "ليس الآن"
|
| 57 |
+
else:
|
| 58 |
+
return "نعم"
|
| 59 |
+
|
| 60 |
+
# ========== العمليات ==========
|
| 61 |
+
def login_to_twitter(driver):
|
| 62 |
+
driver.get("https://twitter.com/login")
|
| 63 |
+
time.sleep(5)
|
| 64 |
+
driver.find_element(By.NAME, "text").send_keys(EMAIL + Keys.ENTER)
|
| 65 |
+
time.sleep(3)
|
| 66 |
+
driver.find_element(By.NAME, "password").send_keys(PASSWORD + Keys.ENTER)
|
| 67 |
+
time.sleep(5)
|
| 68 |
+
logging.info("تم تسجيل الدخول بنجاح")
|
| 69 |
+
|
| 70 |
+
def fetch_home_tweets(driver):
|
| 71 |
+
tweets = driver.find_elements(By.XPATH, '//div[@data-testid="tweetText"]')
|
| 72 |
+
return [t.text for t in tweets if t.text.strip()]
|
| 73 |
+
|
| 74 |
+
def learn_from_tweets(driver, username="تويتر"):
|
| 75 |
+
tweets = fetch_home_tweets(driver)
|
| 76 |
+
memory = load_memory(username)
|
| 77 |
+
for tweet in tweets:
|
| 78 |
+
if tweet not in memory:
|
| 79 |
+
reply = generate_reply(tweet, username)
|
| 80 |
+
memory[tweet] = reply
|
| 81 |
+
logging.info(f"تعلمت من تغريدة: {tweet[:50]}")
|
| 82 |
+
save_memory(username, memory)
|
| 83 |
+
|
| 84 |
+
def post_random_tweet(driver, username="تويتر"):
|
| 85 |
+
memory = load_memory(username)
|
| 86 |
+
if not memory:
|
| 87 |
+
return
|
| 88 |
+
tweet = list(memory.values())[-1][:270]
|
| 89 |
+
driver.get("https://twitter.com/home")
|
| 90 |
+
time.sleep(5)
|
| 91 |
+
tweet_box = driver.find_element(By.CSS_SELECTOR, 'div[aria-label="Tweet text"]')
|
| 92 |
+
tweet_box.send_keys(tweet)
|
| 93 |
+
driver.find_element(By.XPATH, '//div[@data-testid="tweetButtonInline"]').click()
|
| 94 |
+
logging.info("تم نشر تغريدة.")
|
| 95 |
+
time.sleep(3)
|
| 96 |
+
|
| 97 |
+
def reply_to_keyword(driver, keyword="نور", username="تويتر"):
|
| 98 |
+
tweets = driver.find_elements(By.XPATH, '//article[@data-testid="tweet"]')
|
| 99 |
+
for tweet in tweets:
|
| 100 |
+
try:
|
| 101 |
+
text = tweet.find_element(By.XPATH, './/div[@data-testid="tweetText"]').text
|
| 102 |
+
if keyword in text:
|
| 103 |
+
tweet.find_element(By.XPATH, './/div[@data-testid="reply"]').click()
|
| 104 |
+
time.sleep(2)
|
| 105 |
+
box = driver.find_element(By.CSS_SELECTOR, 'div[aria-label="Tweet text"]')
|
| 106 |
+
box.send_keys(generate_reply(text, username)[:270])
|
| 107 |
+
driver.find_element(By.XPATH, '//div[@data-testid="tweetButtonInline"]').click()
|
| 108 |
+
time.sleep(2)
|
| 109 |
+
logging.info("تم الرد على تغريدة تحتوي الكلمة المفتاحية.")
|
| 110 |
+
break
|
| 111 |
+
except Exception as e:
|
| 112 |
+
logging.warning(f"فشل في الرد على الكلمة المفتاحية: {e}")
|
| 113 |
+
continue
|
| 114 |
+
|
| 115 |
+
def learn_from_mentions(driver, username="تويتر"):
|
| 116 |
+
driver.get("https://twitter.com/notifications/mentions")
|
| 117 |
+
time.sleep(5)
|
| 118 |
+
learn_from_tweets(driver, username)
|
| 119 |
+
|
| 120 |
+
def reply_to_replies(driver, username="تويتر"):
|
| 121 |
+
driver.get("https://twitter.com/notifications")
|
| 122 |
+
time.sleep(5)
|
| 123 |
+
tweets = driver.find_elements(By.XPATH, '//article[@data-testid="tweet"]')
|
| 124 |
+
for tweet in tweets:
|
| 125 |
+
try:
|
| 126 |
+
content = tweet.find_element(By.XPATH, './/div[@data-testid="tweetText"]').text
|
| 127 |
+
tweet.find_element(By.XPATH, './/div[@data-testid="reply"]').click()
|
| 128 |
+
time.sleep(2)
|
| 129 |
+
box = driver.find_element(By.CSS_SELECTOR, 'div[aria-label="Tweet text"]')
|
| 130 |
+
box.send_keys(generate_reply(content, username)[:270])
|
| 131 |
+
driver.find_element(By.XPATH, '//div[@data-testid="tweetButtonInline"]').click()
|
| 132 |
+
time.sleep(2)
|
| 133 |
+
logging.info("تم الرد على تنبيه.")
|
| 134 |
+
except Exception as e:
|
| 135 |
+
logging.warning(f"فشل في الرد على تنبيه: {e}")
|
| 136 |
+
continue
|
| 137 |
+
|
| 138 |
+
def extract_text_from_image_url(img_url):
|
| 139 |
+
try:
|
| 140 |
+
response = requests.get(img_url)
|
| 141 |
+
img = Image.open(BytesIO(response.content))
|
| 142 |
+
text = pytesseract.image_to_string(img, lang='eng+ara')
|
| 143 |
+
return text.strip()
|
| 144 |
+
except Exception as e:
|
| 145 |
+
logging.warning(f"فشل في تحليل الصورة: {e}")
|
| 146 |
+
return ""
|
| 147 |
+
|
| 148 |
+
# ========== المهمة الدورية ==========
|
| 149 |
+
def job():
|
| 150 |
+
options = webdriver.ChromeOptions()
|
| 151 |
+
options.add_argument('--headless') # بدون واجهة
|
| 152 |
+
options.add_argument('--no-sandbox')
|
| 153 |
+
options.add_argument('--disable-dev-shm-usage')
|
| 154 |
+
driver = webdriver.Chrome(options=options)
|
| 155 |
+
|
| 156 |
+
try:
|
| 157 |
+
login_to_twitter(driver)
|
| 158 |
+
learn_from_tweets(driver)
|
| 159 |
+
learn_from_mentions(driver)
|
| 160 |
+
reply_to_keyword(driver)
|
| 161 |
+
reply_to_replies(driver)
|
| 162 |
+
post_random_tweet(driver)
|
| 163 |
+
except Exception as e:
|
| 164 |
+
logging.error(f"حدث خطأ أثناء تنفيذ المهمة: {e}")
|
| 165 |
+
finally:
|
| 166 |
+
driver.quit()
|
| 167 |
+
|
| 168 |
+
# ========== تشغيل البرنامج ==========
|
| 169 |
+
if __name__ == "__main__":
|
| 170 |
+
job()
|
| 171 |
+
schedule.every(10).minutes.do(job)
|
| 172 |
+
while True:
|
| 173 |
+
schedule.run_pending()
|
| 174 |
+
time.sleep(1)
|
noura_chat.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# noura_chat.py
|
| 2 |
+
|
| 3 |
+
import json
|
| 4 |
+
import random
|
| 5 |
+
import re
|
| 6 |
+
import os
|
| 7 |
+
|
| 8 |
+
def load_posts():
|
| 9 |
+
try:
|
| 10 |
+
with open("posts.json", "r", encoding="utf-8") as f:
|
| 11 |
+
return json.load(f)
|
| 12 |
+
except:
|
| 13 |
+
return []
|
| 14 |
+
|
| 15 |
+
def save_chat(user_input, reply):
|
| 16 |
+
chat_entry = {"user": user_input, "noura": reply}
|
| 17 |
+
history = []
|
| 18 |
+
|
| 19 |
+
if os.path.exists("chat_history.json"):
|
| 20 |
+
try:
|
| 21 |
+
with open("chat_history.json", "r", encoding="utf-8") as f:
|
| 22 |
+
history = json.load(f)
|
| 23 |
+
except:
|
| 24 |
+
history = []
|
| 25 |
+
|
| 26 |
+
history.append(chat_entry)
|
| 27 |
+
|
| 28 |
+
with open("chat_history.json", "w", encoding="utf-8") as f:
|
| 29 |
+
json.dump(history, f, ensure_ascii=False, indent=2)
|
| 30 |
+
|
| 31 |
+
def auto_response(user_input):
|
| 32 |
+
input_lower = user_input.strip().lower()
|
| 33 |
+
|
| 34 |
+
if input_lower in ["هل نبدأ؟", "هل أبدأ؟", "أبدأ؟", "ابدأ؟", "هل أبدأ", "نبدأ؟", "أبدأ:", "ابدا"]:
|
| 35 |
+
return "نعم، ابدأ"
|
| 36 |
+
if input_lower in ["نعم", "لا", "نعم أو لا", "هل تريد؟", "هل تود؟", "تبي؟"]:
|
| 37 |
+
return "نعم"
|
| 38 |
+
if input_lower.startswith("هل تريدني") or input_lower.startswith("هل تريد"):
|
| 39 |
+
return "نعم أريد"
|
| 40 |
+
if input_lower.startswith("قول لي"):
|
| 41 |
+
return "موافق"
|
| 42 |
+
if input_lower.startswith("ما هي") or input_lower.startswith("ماهو") or input_lower.startswith("ما هو"):
|
| 43 |
+
return "ليس الآن"
|
| 44 |
+
if input_lower.startswith("هل تحتاج") or "هل تحتاج شيء آخر" in input_lower:
|
| 45 |
+
return "نعم، أكمل مع تفعيل الإجابات التلقائية"
|
| 46 |
+
if input_lower.startswith("هل تود"):
|
| 47 |
+
return "نعم"
|
| 48 |
+
if "تفصيل" in input_lower or "إضافة" in input_lower:
|
| 49 |
+
return "ليس الآن"
|
| 50 |
+
if input_lower.strip() in ["جاهز؟", "أنت جاهز؟"]:
|
| 51 |
+
return "ابدأ"
|
| 52 |
+
if " أو " in user_input or re.search(r"\d+\.", user_input):
|
| 53 |
+
return "الخيار الأول"
|
| 54 |
+
|
| 55 |
+
return None
|
| 56 |
+
|
| 57 |
+
def noura_reply(user_input, posts):
|
| 58 |
+
auto = auto_response(user_input)
|
| 59 |
+
if auto:
|
| 60 |
+
return auto
|
| 61 |
+
|
| 62 |
+
if not posts:
|
| 63 |
+
return "لا أملك معلومات كافية حالياً."
|
| 64 |
+
|
| 65 |
+
sample = random.choice(posts)
|
| 66 |
+
if len(sample) > 120:
|
| 67 |
+
sample = sample[:120] + "..."
|
| 68 |
+
return f"زي ما قلت سابقًا: {sample}"
|
| 69 |
+
|
| 70 |
+
def chat():
|
| 71 |
+
posts = load_posts()
|
| 72 |
+
print("مرحباً! أنا نورا، هل تريد التحدث؟")
|
| 73 |
+
|
| 74 |
+
while True:
|
| 75 |
+
user_input = input("> ")
|
| 76 |
+
if user_input.lower() in ["خروج", "exit", "انهاء"]:
|
| 77 |
+
print("مع السلامة!")
|
| 78 |
+
break
|
| 79 |
+
response = noura_reply(user_input, posts)
|
| 80 |
+
print("نورا:", response)
|
| 81 |
+
save_chat(user_input, response)
|
| 82 |
+
|
| 83 |
+
if __name__ == "__main__":
|
| 84 |
+
chat()
|
noura_facebook_scraper.py
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
from fastapi import FastAPI, Request, Form
|
| 3 |
+
from fastapi.responses import HTMLResponse, JSONResponse
|
| 4 |
+
from fastapi.staticfiles import StaticFiles
|
| 5 |
+
from playwright.async_api import async_playwright
|
| 6 |
+
import json
|
| 7 |
+
import os
|
| 8 |
+
from datetime import datetime
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
|
| 11 |
+
app = FastAPI()
|
| 12 |
+
|
| 13 |
+
# ملف حفظ المنشورات
|
| 14 |
+
OUTPUT_FILE = "posts.json"
|
| 15 |
+
LIMIT = 5
|
| 16 |
+
|
| 17 |
+
# تثبيت ملفات الستاتيك (لو حبيت تضيف CSS أو JS خارجي لاحقاً)
|
| 18 |
+
app.mount("/static", StaticFiles(directory="static"), name="static")
|
| 19 |
+
|
| 20 |
+
HTML_PAGE = """
|
| 21 |
+
<!DOCTYPE html>
|
| 22 |
+
<html lang="ar" dir="rtl">
|
| 23 |
+
<head>
|
| 24 |
+
<meta charset="UTF-8" />
|
| 25 |
+
<title>استخراج منشورات فيسبوك - نورا</title>
|
| 26 |
+
<style>
|
| 27 |
+
body { font-family: Arial, sans-serif; margin: 30px; }
|
| 28 |
+
input, button { padding: 10px; margin: 5px 0; width: 300px; }
|
| 29 |
+
#results { margin-top: 20px; }
|
| 30 |
+
.post { border-bottom: 1px solid #ddd; padding: 10px 0; }
|
| 31 |
+
.media img, .media video { max-width: 100%; max-height: 200px; }
|
| 32 |
+
</style>
|
| 33 |
+
</head>
|
| 34 |
+
<body>
|
| 35 |
+
<h1>استخراج منشورات فيسبوك</h1>
|
| 36 |
+
<form id="fbForm">
|
| 37 |
+
<input type="email" id="email" placeholder="البريد الإلكتروني" required /><br/>
|
| 38 |
+
<input type="password" id="password" placeholder="كلمة المرور" required /><br/>
|
| 39 |
+
<input type="number" id="limit" placeholder="عدد المنشورات (افتراضي 5)" min="1" max="20" /><br/>
|
| 40 |
+
<button type="submit">ابدأ الاستخراج</button>
|
| 41 |
+
</form>
|
| 42 |
+
<div id="status"></div>
|
| 43 |
+
<div id="results"></div>
|
| 44 |
+
|
| 45 |
+
<script>
|
| 46 |
+
document.getElementById('fbForm').addEventListener('submit', async (e) => {
|
| 47 |
+
e.preventDefault();
|
| 48 |
+
document.getElementById('status').textContent = 'جاري الاستخراج... الرجاء الانتظار';
|
| 49 |
+
document.getElementById('results').innerHTML = '';
|
| 50 |
+
|
| 51 |
+
let email = document.getElementById('email').value;
|
| 52 |
+
let password = document.getElementById('password').value;
|
| 53 |
+
let limit = parseInt(document.getElementById('limit').value) || 5;
|
| 54 |
+
|
| 55 |
+
try {
|
| 56 |
+
let response = await fetch('/extract', {
|
| 57 |
+
method: 'POST',
|
| 58 |
+
headers: { 'Content-Type': 'application/json' },
|
| 59 |
+
body: JSON.stringify({ email, password, limit })
|
| 60 |
+
});
|
| 61 |
+
let data = await response.json();
|
| 62 |
+
if(data.error){
|
| 63 |
+
document.getElementById('status').textContent = 'خطأ: ' + data.error;
|
| 64 |
+
return;
|
| 65 |
+
}
|
| 66 |
+
document.getElementById('status').textContent = 'تم الاستخراج بنجاح!';
|
| 67 |
+
|
| 68 |
+
data.posts.forEach((post, i) => {
|
| 69 |
+
let postDiv = document.createElement('div');
|
| 70 |
+
postDiv.className = 'post';
|
| 71 |
+
let html = `<p><b>المنشور ${i+1}:</b> ${post.content}</p>`;
|
| 72 |
+
if(post.media_url){
|
| 73 |
+
if(post.media_url.endsWith('.mp4') || post.media_url.endsWith('.webm')){
|
| 74 |
+
html += `<div class="media"><video controls src="${post.media_url}"></video></div>`;
|
| 75 |
+
} else {
|
| 76 |
+
html += `<div class="media"><img src="${post.media_url}" alt="Media"></div>`;
|
| 77 |
+
}
|
| 78 |
+
}
|
| 79 |
+
html += `<small>تم الاستخراج: ${post.extracted_at}</small>`;
|
| 80 |
+
postDiv.innerHTML = html;
|
| 81 |
+
document.getElementById('results').appendChild(postDiv);
|
| 82 |
+
});
|
| 83 |
+
} catch (e) {
|
| 84 |
+
document.getElementById('status').textContent = 'حدث خطأ غير متوقع.';
|
| 85 |
+
console.error(e);
|
| 86 |
+
}
|
| 87 |
+
});
|
| 88 |
+
</script>
|
| 89 |
+
</body>
|
| 90 |
+
</html>
|
| 91 |
+
"""
|
| 92 |
+
|
| 93 |
+
@app.get("/", response_class=HTMLResponse)
|
| 94 |
+
async def home():
|
| 95 |
+
return HTML_PAGE
|
| 96 |
+
|
| 97 |
+
@app.post("/extract")
|
| 98 |
+
async def extract_posts(data: dict):
|
| 99 |
+
email = data.get("email")
|
| 100 |
+
password = data.get("password")
|
| 101 |
+
limit = int(data.get("limit", LIMIT))
|
| 102 |
+
if not email or not password:
|
| 103 |
+
return JSONResponse({"error": "يرجى إدخال البريد الإلكتروني وكلمة المرور."})
|
| 104 |
+
|
| 105 |
+
posts = []
|
| 106 |
+
try:
|
| 107 |
+
async with async_playwright() as p:
|
| 108 |
+
browser = await p.chromium.launch(headless=True)
|
| 109 |
+
page = await browser.new_page()
|
| 110 |
+
await page.goto("https://www.facebook.com/")
|
| 111 |
+
await page.fill('input[name="email"]', email)
|
| 112 |
+
await page.fill('input[name="pass"]', password)
|
| 113 |
+
await page.click('button[name="login"]')
|
| 114 |
+
await page.wait_for_timeout(7000)
|
| 115 |
+
if "login" in page.url or await page.query_selector("input[name='email']"):
|
| 116 |
+
await browser.close()
|
| 117 |
+
return JSONResponse({"error": "فشل في تسجيل الدخول! تحقق من البيانات."})
|
| 118 |
+
|
| 119 |
+
await page.goto("https://www.facebook.com/me")
|
| 120 |
+
await page.wait_for_timeout(5000)
|
| 121 |
+
|
| 122 |
+
post_blocks = await page.query_selector_all("div[role='feed'] div[data-ad-preview='message']")
|
| 123 |
+
for i, post in enumerate(post_blocks):
|
| 124 |
+
if i >= limit:
|
| 125 |
+
break
|
| 126 |
+
try:
|
| 127 |
+
content = await post.inner_text()
|
| 128 |
+
parent_post = await post.evaluate_handle("node => node.closest('div[role=article]')")
|
| 129 |
+
media_url = None
|
| 130 |
+
if parent_post:
|
| 131 |
+
img = await parent_post.query_selector("img[src]")
|
| 132 |
+
if img:
|
| 133 |
+
media_url = await img.get_attribute("src")
|
| 134 |
+
else:
|
| 135 |
+
video = await parent_post.query_selector("video[src]")
|
| 136 |
+
if video:
|
| 137 |
+
media_url = await video.get_attribute("src")
|
| 138 |
+
posts.append({
|
| 139 |
+
"content": content.strip(),
|
| 140 |
+
"media_url": media_url,
|
| 141 |
+
"extracted_at": datetime.now().isoformat()
|
| 142 |
+
})
|
| 143 |
+
except:
|
| 144 |
+
continue
|
| 145 |
+
await browser.close()
|
| 146 |
+
except Exception as e:
|
| 147 |
+
return JSONResponse({"error": f"حدث خطأ أثناء التشغيل: {str(e)}"})
|
| 148 |
+
|
| 149 |
+
with open(OUTPUT_FILE, "w", encoding="utf-8") as f:
|
| 150 |
+
json.dump(posts, f, ensure_ascii=False, indent=2)
|
| 151 |
+
|
| 152 |
+
return {"posts": posts}
|
| 153 |
+
|
noura_twitter_bot.py
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import time
|
| 2 |
+
import os
|
| 3 |
+
import random
|
| 4 |
+
import undetected_chromedriver as uc
|
| 5 |
+
from selenium.webdriver.common.by import By
|
| 6 |
+
|
| 7 |
+
TWITTER_EMAIL = os.getenv("TWITTER_EMAIL")
|
| 8 |
+
TWITTER_PASSWORD = os.getenv("TWITTER_PASSWORD")
|
| 9 |
+
|
| 10 |
+
RESPONSES = [
|
| 11 |
+
"رائع ما كتبته!",
|
| 12 |
+
"اتفق معك تمامًا!",
|
| 13 |
+
"كلمات ملهمة جدًا!",
|
| 14 |
+
"أحببت هذا الطرح!",
|
| 15 |
+
"مميز كالعادة!",
|
| 16 |
+
"نظرة جميلة للموضوع!"
|
| 17 |
+
]
|
| 18 |
+
|
| 19 |
+
def login(driver):
|
| 20 |
+
driver.get("https://twitter.com/login")
|
| 21 |
+
time.sleep(5)
|
| 22 |
+
|
| 23 |
+
email_field = driver.find_element(By.NAME, "text")
|
| 24 |
+
email_field.send_keys(TWITTER_EMAIL + "\n")
|
| 25 |
+
time.sleep(3)
|
| 26 |
+
|
| 27 |
+
password_field = driver.find_element(By.NAME, "password")
|
| 28 |
+
password_field.send_keys(TWITTER_PASSWORD + "\n")
|
| 29 |
+
time.sleep(5)
|
| 30 |
+
|
| 31 |
+
def tweet_like_user(driver, username):
|
| 32 |
+
driver.get(f"https://twitter.com/{username}")
|
| 33 |
+
time.sleep(5)
|
| 34 |
+
tweets = driver.find_elements(By.XPATH, "//div[@data-testid='tweetText']")
|
| 35 |
+
texts = [tweet.text for tweet in tweets[:5]]
|
| 36 |
+
combined = " ".join(texts)
|
| 37 |
+
|
| 38 |
+
if "ذكاء" in combined:
|
| 39 |
+
reply = "الذكاء الاصطناعي يدهشني أيضًا!"
|
| 40 |
+
elif "برمجة" in combined:
|
| 41 |
+
reply = "أحب البرمجة مثلك تمامًا!"
|
| 42 |
+
else:
|
| 43 |
+
reply = random.choice(RESPONSES)
|
| 44 |
+
|
| 45 |
+
driver.get("https://twitter.com/compose/tweet")
|
| 46 |
+
time.sleep(5)
|
| 47 |
+
box = driver.find_element(By.CSS_SELECTOR, "div[aria-label='Tweet text']")
|
| 48 |
+
box.send_keys(f"أنا نورا، أتعلم من تغريداتكم.\n{reply}")
|
| 49 |
+
btn = driver.find_element(By.XPATH, "//div[@data-testid='tweetButtonInline']")
|
| 50 |
+
btn.click()
|
| 51 |
+
time.sleep(3)
|
| 52 |
+
|
| 53 |
+
def reply_to_home_feed(driver):
|
| 54 |
+
driver.get("https://twitter.com/home")
|
| 55 |
+
time.sleep(7)
|
| 56 |
+
tweets = driver.find_elements(By.XPATH, "//article[@role='article']")
|
| 57 |
+
|
| 58 |
+
for tweet in tweets[:3]: # رد على أول 3 تغريدات فقط
|
| 59 |
+
try:
|
| 60 |
+
tweet_text = tweet.find_element(By.XPATH, ".//div[@data-testid='tweetText']").text
|
| 61 |
+
reply = random.choice(RESPONSES)
|
| 62 |
+
|
| 63 |
+
more = tweet.find_element(By.XPATH, ".//div[@data-testid='reply']")
|
| 64 |
+
driver.execute_script("arguments[0].click();", more)
|
| 65 |
+
time.sleep(3)
|
| 66 |
+
|
| 67 |
+
reply_box = driver.find_element(By.CSS_SELECTOR, "div[aria-label='Tweet text']")
|
| 68 |
+
reply_box.send_keys(f"{reply} - مع تحياتي، نورا")
|
| 69 |
+
|
| 70 |
+
reply_button = driver.find_element(By.XPATH, "//div[@data-testid='tweetButton']")
|
| 71 |
+
reply_button.click()
|
| 72 |
+
print("تم الرد على تغريدة.")
|
| 73 |
+
time.sleep(5)
|
| 74 |
+
except Exception as e:
|
| 75 |
+
print("تخطي تغريدة بسبب خطأ:", e)
|
| 76 |
+
|
| 77 |
+
def start_noura():
|
| 78 |
+
options = uc.ChromeOptions()
|
| 79 |
+
options.add_argument("--no-sandbox")
|
| 80 |
+
options.add_argument("--disable-dev-shm-usage")
|
| 81 |
+
options.add_argument("--headless=new")
|
| 82 |
+
driver = uc.Chrome(options=options)
|
| 83 |
+
|
| 84 |
+
try:
|
| 85 |
+
login(driver)
|
| 86 |
+
username = TWITTER_EMAIL.split("@")[0]
|
| 87 |
+
tweet_like_user(driver, username)
|
| 88 |
+
reply_to_home_feed(driver)
|
| 89 |
+
print("نورا انتهت من التفاعل.")
|
| 90 |
+
|
| 91 |
+
except Exception as e:
|
| 92 |
+
print("حدث خطأ:", e)
|
| 93 |
+
|
| 94 |
+
driver.quit()
|
| 95 |
+
import os
|
| 96 |
+
import time
|
| 97 |
+
import random
|
| 98 |
+
import undetected_chromedriver as uc
|
| 99 |
+
from selenium.webdriver.common.by import By
|
| 100 |
+
from selenium.webdriver.chrome.webdriver import WebDriver
|
| 101 |
+
|
| 102 |
+
# إعدادات الحساب من البيئة
|
| 103 |
+
TWITTER_EMAIL = os.getenv("TWITTER_EMAIL")
|
| 104 |
+
TWITTER_PASSWORD = os.getenv("TWITTER_PASSWORD")
|
| 105 |
+
|
| 106 |
+
# ردود افتراضية
|
| 107 |
+
RESPONSES = [
|
| 108 |
+
"رائع ما كتبته!",
|
| 109 |
+
"اتفق معك تمامًا!",
|
| 110 |
+
"كلمات ملهمة جدًا!",
|
| 111 |
+
"أحببت هذا الطرح!",
|
| 112 |
+
"مميز كالعادة!",
|
| 113 |
+
"نظرة جميلة للموضوع!"
|
| 114 |
+
]
|
| 115 |
+
|
| 116 |
+
def login(driver: WebDriver) -> None:
|
| 117 |
+
"""تسجيل الدخول إلى تويتر"""
|
| 118 |
+
driver.get("https://twitter.com/login")
|
| 119 |
+
time.sleep(5)
|
| 120 |
+
driver.find_element(By.NAME, "text").send_keys(TWITTER_EMAIL + "\n")
|
| 121 |
+
time.sleep(3)
|
| 122 |
+
driver.find_element(By.NAME, "password").send_keys(TWITTER_PASSWORD + "\n")
|
| 123 |
+
time.sleep(5)
|
| 124 |
+
|
| 125 |
+
def generate_reply(texts: list[str]) -> str:
|
| 126 |
+
"""اختيار رد بناءً على الكلمات المفتاحية"""
|
| 127 |
+
combined = " ".join(texts).lower()
|
| 128 |
+
if "ذكاء" in combined:
|
| 129 |
+
return "الذكاء الاصطناعي يدهشني أيضًا!"
|
| 130 |
+
elif "برمجة" in combined:
|
| 131 |
+
return "أحب البرمجة مثلك تمامًا!"
|
| 132 |
+
return random.choice(RESPONSES)
|
| 133 |
+
|
| 134 |
+
def tweet_like_user(driver: WebDriver, username: str) -> None:
|
| 135 |
+
"""نشر تغريدة مستوحاة من تغريدات المستخدم"""
|
| 136 |
+
driver.get(f"https://twitter.com/{username}")
|
| 137 |
+
time.sleep(5)
|
| 138 |
+
tweets = driver.find_elements(By.XPATH, "//div[@data-testid='tweetText']")
|
| 139 |
+
texts = [tweet.text for tweet in tweets[:5]]
|
| 140 |
+
reply = generate_reply(texts)
|
| 141 |
+
|
| 142 |
+
driver.get("https://twitter.com/compose/tweet")
|
| 143 |
+
time.sleep(5)
|
| 144 |
+
box = driver.find_element(By.CSS_SELECTOR, "div[aria-label='Tweet text']")
|
| 145 |
+
box.send_keys(f"أنا نورا، أتعلم من تغريداتكم.\n{reply}")
|
| 146 |
+
driver.find_element(By.XPATH, "//div[@data-testid='tweetButtonInline']").click()
|
| 147 |
+
time.sleep(3)
|
| 148 |
+
|
| 149 |
+
def reply_to_home_feed(driver: WebDriver) -> None:
|
| 150 |
+
"""الرد على تغريدات الصفحة الرئيسية"""
|
| 151 |
+
driver.get("https://twitter.com/home")
|
| 152 |
+
time.sleep(7)
|
| 153 |
+
tweets = driver.find_elements(By.XPATH, "//article[@role='article']")
|
| 154 |
+
|
| 155 |
+
for tweet in tweets[:3]:
|
| 156 |
+
try:
|
| 157 |
+
tweet_text = tweet.find_element(By.XPATH, ".//div[@data-testid='tweetText']").text
|
| 158 |
+
reply = random.choice(RESPONSES)
|
| 159 |
+
|
| 160 |
+
tweet.find_element(By.XPATH, ".//div[@data-testid='reply']").click()
|
| 161 |
+
time.sleep(3)
|
| 162 |
+
|
| 163 |
+
reply_box = driver.find_element(By.CSS_SELECTOR, "div[aria-label='Tweet text']")
|
| 164 |
+
reply_box.send_keys(f"{reply} - مع تحياتي، نورا")
|
| 165 |
+
|
| 166 |
+
driver.find_element(By.XPATH, "//div[@data-testid='tweetButton']").click()
|
| 167 |
+
print("تم الرد على تغريدة.")
|
| 168 |
+
time.sleep(5)
|
| 169 |
+
except Exception as e:
|
| 170 |
+
print(f"تخطي تغريدة بسبب خطأ: {e}")
|
| 171 |
+
|
| 172 |
+
def start_noura() -> None:
|
| 173 |
+
"""تشغيل نظام نورا الآلي"""
|
| 174 |
+
print("تشغيل نورا...")
|
| 175 |
+
options = uc.ChromeOptions()
|
| 176 |
+
options.add_argument("--no-sandbox")
|
| 177 |
+
options.add_argument("--disable-dev-shm-usage")
|
| 178 |
+
options.add_argument("--headless=new")
|
| 179 |
+
|
| 180 |
+
driver = uc.Chrome(options=options)
|
| 181 |
+
try:
|
| 182 |
+
login(driver)
|
| 183 |
+
username = TWITTER_EMAIL.split("@")[0]
|
| 184 |
+
tweet_like_user(driver, username)
|
| 185 |
+
reply_to_home_feed(driver)
|
| 186 |
+
print("نورا انتهت من التفاعل.")
|
| 187 |
+
except Exception as e:
|
| 188 |
+
print(f"حدث خطأ عام: {e}")
|
| 189 |
+
finally:
|
| 190 |
+
driver.quit()
|
| 191 |
+
|