@המלאך כתב בהמלצה | המלצה לפרויקט:
@עידו300 זה יעלה כסף, לימות המשיח.
למה שיעלה כסף?
וגם זה כן דורש ידע טכנית במערכות ivr בכלל, ושל ימות המשיח בפרט.
בהחלט דורש ידע טכני, אבל לא יותר מידי, הכל שם די מפורט והקהילה די עונה מהר.
@המלאך כתב בהמלצה | המלצה לפרויקט:
@עידו300 זה יעלה כסף, לימות המשיח.
למה שיעלה כסף?
וגם זה כן דורש ידע טכנית במערכות ivr בכלל, ושל ימות המשיח בפרט.
בהחלט דורש ידע טכני, אבל לא יותר מידי, הכל שם די מפורט והקהילה די עונה מהר.
@שלמה-קופלוביץ מישהו די מזמן הציע לי לבנות מערכת מכירות (על בסיס המערכת של ימות המשיח) שתתופעל ע"י פלאפונים כשרים, כיום בשביל מערכת כזו חייבים מחשב, ומערכת כזו שלא יצטרכו בשבילה מחשב יכולה לעזור מאוד לבעלי מכירות המחזיקים רק מכשירים כשרים.
זה פרוקיט לא פשוט אבל גם לא בשמים, אני חושב שהרבה יודו לך אם תעשה את זה.
(אני מאמין שזה גם יכול להיות רווחי...)
@שלמה-קופלוביץ API גם טוב?
@אבי-6 אתה יכול לשאול AI על קוד שידמה לחיצות, אין לי הרבה ניסיון עם זה, אבל אין סיבה שלא יעבוד.
כהמשך לדיון פה, האם הטענה הבאה נכונה?
השאלה שלי היא כי AI למיניהם טענו שכ"כ הרבה join מהוה עומס על השרת ומכביד סתם על כל תהליך השליפה, מה שא"כ אם שליפה מחלק מהטבלאות עושים ע"י בקשה שניה בקוד עצמו שאז אמנם זה לא שאילתא אחת מסודרת אבל זה לא מכריח את השרת לחבר טבלאות ולהשוות ביניהם. האם זו טענה נכונה וכזו כמות עדיף לא לחבר ולסנן (במקרה הצורך) בבת אחת או שזה שטויות ואין עם זה שום בעיה.
@אבי-6 תצטרך שרת אני חושב.
שים לב שהאנטרנט יהיה לא מסונן!
אני מאמין שאתה לא הולך לעקוב אחרי האתר ולמצוא את הAPI, וגם לא בטוח שזה אפשרי, לכן יש אפשרות של דימוי לחיצות, כאילו אתה גולש, רק שהשרת עושה את זה במקומך, הוא יצטרך גם למשוך את הSMS האחרון מהמערכת ולזהות שם את הקוד (לא כזה מורכב).
אני די בטוח שAI כלשהו יוכל לעשות את זה בשבילך.
@א.מ.ד. כיום איך אפשר להשתמש?
@א.מ.ד. אפשר להשתמש בזה דרך ollama?
@אבי-6 מערכת -קו - אפשר בד"כ בחינם.
לא כ"כ הבנתי מה אתה רוצה, אבל סביר להניח שיהיה בתשלום.
תוכל יותר לפרט כאן או בstamandsefer של ג'ימייל.
עשיתי שינוי, לא גנרי ולא clean code אבל קריא וטוב
מה אומרים?
export async function findAdByFilter(filters = {}) {
if (!filters || Object.keys(filters).length === 0) {return errorResponse("לא סופקו פילטרים חוקיים");}
try {
let queryBuilder = knex("advertiser_ads as M").select("M.*").distinct();
if (filters.id && checkNumber(filters.id)) {queryBuilder.where("M.id", filters.id);}
if (filters.phoneToSearch && isValidIsraeliPhone(filters.phoneToSearch)) {queryBuilder.where("M.phone", filters.phoneToSearch);}
if (filters.phoneOfSearcher && isValidIsraeliPhone(filters.phoneOfSearcher)) {
queryBuilder.select(
knex.raw(
`EXISTS (
SELECT 1
FROM ads_read MK
WHERE MK.id = M.id
AND MK.phone = ?
) as was_read`
, [filters.phoneOfSearcher])
);
}
if (filters.profession && checkProfession(filters.profession)) {queryBuilder.where("M.profession", filters.profession);}
if (filters.min_price != null && checkNumber(filters.min_price)) {queryBuilder.where("M.min_price", ">=", filters.min_price);}
if (filters.area && filters.area === "כל הארץ" && filters.city && filters.city !== "כל הארץ") {return errorResponse("לא ניתן לספק עיר לסינון כאשר האזור הוא 'כל הארץ'");}
if (filters.area && filters.area !== "כל הארץ") {
if (!checkArea(filters.area)) {return errorResponse("אזור לא חוקי לסינון");}
if (filters.city && (filters.city === "כל הארץ" || !checkCity(filters.city))) {return errorResponse("יש לספק עיר חוקית לסינון או לא לספק עיר כלל");}
if (filters.city && !checkCityInArea(filters.city, filters.area)) {return errorResponse("העיר לא נמצאת באותו אזור שסופק לסינון");}
queryBuilder.leftJoin("advertiser_cities as E", "E.adId", "M.id");
if (filters.city)
{queryBuilder.where(function() {
this.whereNotNull("E.city").where("E.city", filters.city)
.orWhere(function(){
this.whereNotNull("E.area").where("E.area", filters.area)
.orWhere(function(){
this.whereNull("E.city").whereNull("E.area");})
})
});}
else {
queryBuilder.where(function() {
this.whereNotNull("E.area").where("E.area", filters.area)
.orWhere(function(){
this.whereNull("E.area").whereNull("E.city");})
})
}
}
const results = await queryBuilder;
return results;
}
catch (error) {
console.error("[findAdByFilter] Error:", error);
return errorResponse("שגיאה בשליפת המודעה לפי פילטרים");
}
}
@חיים-יענקל-0 קו עולה 50 ש"ח ח"פ (יש גם יותר יקרים) יש פרסומות כמו כל הקוים של ימות המשיח, עולה בערך 10 ש"ח להוריד אותם (אא"כ זה מוסדי).
עכשיו המענה טלפוני לא פעיל, אפשר לשלוח מייל, אם תרצה אוכל לבקש שיחזרו אליך (אני לא קשור אליהם ואני לא מרוויח מכך כלום).
cs@nbs-app.net
072-2777222
@חיים-יענקל-0 יש ריסיילר כשר בהכשר הוועדה (דיברתי עם ועד הרבנים בעצמי והם אמרו לי שהחברה הנ"ל מאושרת) אם תרצה, את כל שאר החברות המאושרות אני לא מכיר. אבל כמה ששמעתי (בגדר לשון הרע ספק הוצאת שם רע) הן פחות נוחות ולא כ"כ חינמיות.
אם תיקיית הroot גלויה לכולם, איפה אפשר לשמור קבצים שלא רוצים שיהיו גלוים לכולם (קבצי הגדרות, nodejs ועוד)? ולמה לטס אנקריפט יוצרים בה את הקבצים שלהם? הרי זה גלוי לכל.
@מחובר-23 לפחות היית עונה גם משהו מועיל...
מישהו?
אני צריך לכתוב פונקציה שתקבל מודעות ממסד נתונים על פי פילטרים אופציונליים, הAI הציעו את שלהם וכל הזמן היא מושלמת, ועם זאת כל הזמן יש בה באגים שיכולים להקריס אותה.
אשמח לעזרה, הפונקציה קצת מורכבת, יש את הטבלה ה"ראשית", ויש שתי טבלאות מקושרות, 1 ערים ו1 נקרא או לא נקרא.
בינתיים התעסקתי רק עם הסינון + ערים, עוד לא הוספתי את הנקרא/לא נקרא, אשמח לעזרה בזה.
פונקציות עזר כלליות
const schemaAdvertiser = {
phone: {validate: isValidIsraeliPhone, required: true},
profession: {validate: checkProfession, required: true},
min_price: {validate: checkNumber, required: false},
path: {validate: (path) => typeof path === 'string' && path.trim() !== '', required: false}
};
const schemaLocation = {
area: {validate: checkArea, required: false},
city: {validate: checkCity, required: false},
};
function validateParams(params, schema, checkRequired = true) {
if (!params || typeof params !== 'object') {
return errorResponse("Invalid parameters input");
}
const cleanParams = {};
for (const key in schema) {
const field = schema[key];
const value = params[key];
if (value === undefined) {
if (checkRequired && field.required) {
return errorResponse(`Missing required parameter: ${key}`);
}
continue;
}
if (!field.validate(value)) {
return errorResponse(`Invalid value for ${key}`);
}
cleanParams[key] = value;
}
for (const key in params) {
if (!schema[key]) {
return errorResponse(`Unknown parameter: ${key}`);
}
}
return successResponse(cleanParams);
}
function validateLocationParams(locationParams) {
const locationsArray = Array.isArray(locationParams) ? locationParams : [locationParams];
let cleanLocations = [];
for (const loc of locationsArray) {
const validatedLocation = validateParams(loc, schemaLocation, false);
if (!validatedLocation.success) return validatedLocation;
if (validatedLocation.data.city && !validatedLocation.data.area) {
return errorResponse("City provided without area");
}
const { city, area } = validatedLocation.data;
if (city && area && city !== "כל הארץ" && area !== "כל הארץ") {
if (!checkCityInArea(city, area)) {
return errorResponse("City does not belong to the given area");
}
}
cleanLocations.push(validatedLocation.data);
}
return successResponse(cleanLocations);
}
הפונקציה שלשמה התכנסנו
import knex from "knex";
import {areas} from "./lists";
/**
* הגדרת שדות מותרים לסינון והאופרטור שלהם
*/
const FILTER_CONFIG = {
phone: '=',
profession: '=',
min_price: '>='
};
export async function findAdByFilter(filters = {}) {
const { path, ...schemaSearch } = schemaAdvertiser;
const validated = validateParams(filters, { ...schemaSearch, ...schemaLocation }, false);
if (!validated.success) return validated;
if (Object.keys(validated.data).length === 0) {
return errorResponse("לא סופקו פילטרים חוקיים");
}
try {
const { city, area, ...activeFilters } = validated.data;
const result = await knex("ads as M")
.modify(q => {
if (city || area) {
q.join("advertiser_cities as C", "C.adId", "M.id");
}
if (city) {
const relatedAreas = Array.isArray(city)
? getAreasForCities(city)
: [getCityArea(city)].filter(Boolean);
if (Array.isArray(city)) {
q.where(function() {
this.whereIn("C.city", city)
.orWhereIn("C.area", relatedAreas);
});
} else {
q.where(function() {
this.where("C.city", city)
.orWhere("C.area", relatedAreas[0]);
});
}
} else if (area) {
Array.isArray(area)
? q.whereIn("C.area", area)
: q.where("C.area", area);
}
Object.entries(FILTER_CONFIG).forEach(([field, operator]) => {
const value = activeFilters[field];
if (value !== undefined && value !== null && value !== "") {
Array.isArray(value)
? q.whereIn(`M.${field}`, value)
: q.where(`M.${field}`, operator, value);
}
});
})
.select("M.*")
.distinct("M.id");
return successResponse({ ads: result });
} catch (error) {
console.error("[findAdByFilter] Error:", error);
return errorResponse("שגיאה בשליפת המודעה לפי פילטרים");
}
}
function getCityArea(city) {
for (const [area, cities] of Object.entries(areas)) {
if (cities.includes(city)) return area;
}
return null;
}
function getAreasForCities(citiesArray) {
return [...new Set(citiesArray.map(getCityArea).filter(Boolean))];
}
הקוד מחולק בכל מיני מקומות, מקווה שצירפתי כל מה שצריך.
טבלה ראשית:
ID
טלפון - phone
מקצוע - profession
מחיר מינימום - min_price
נתיב הקלטה - path
סטטוס - status
ערים:
ID, עיר, אזור.
מודעות שנקראו:
ID, טלפון
לא חייבים להצמד לפונקציה הזו, העיקר שיהיה משהו שיעבוד... הAI כבר עשו לי כאב ראש...
@א.מ.ד. לא עקבתי אחרי כל הדיון, כבר שאלו את נטפרי?
@המלאך לפי מה שכתוב זה משהו בסיסי, אם רוצים יותר מתקדם זה בתשלום, עשיתי פעם בדיקה קטנה, לא היה משהו חינמי אמיתי או ברמה כמו ימות המשיח (אבל אולי יש ולא ראיתי...)
@המלאך לא מכיר עוד חינמית