const express = require(“express”);
const fs = require(“fs”);
const session = require(“express-session”);
const fileUpload = require(“express-fileupload”);
const app = express();
const fuzzball = require(“fuzzball”);
const mysql = require(‘mysql’);

const connection = mysql.createConnection({
host: ‘localhost’,
user: ‘music’, // замените на свой логин
password: ‘password’, // замените на свой пароль
database: ‘music’ // замените на свою базу данных
});

connection.connect((err) => {
if (err) {
console.error(‘Ошибка подключения к базе данных: ‘, err);
} else {
console.log(‘Подключение к базе данных успешно’);
}
});

app.set(“view engine”, “ejs”);
app.use(express.static(“public”));

app.use(express.urlencoded({ extended: true }));
app.use(fileUpload());
app.use(session({
secret: “mysecretkey”,
resave: false,
saveUninitialized: false
}));

const citiesAndRegions = JSON.parse(fs.readFileSync(“./db/russia.json”, “utf8”));


//const predefinedGenres = [‘Rock’, ‘Pop’, ‘Jazz’, ‘Hip Hop’, ‘Electronic’, ‘Blues’];

// Функция для получения последних музыкантов, зарегистрированных музыкантов
function getLastNRegisteredMusicians(N, callback) {
connection.query(“SELECT * FROM users ORDER BY id DESC LIMIT ?”, [N], (err, result) => {
if (err) {
console.error("Ошибка при получении последних зарегистрированных музыкантов: ", err);
return callback(err);
} else {
return callback(null, result);
}
});
}

function getMusicians(callback) {
connection.query(“SELECT * FROM users”, (err, result) => {
if (err) {
console.error("Ошибка при получении списка музыкантов: ", err);
return callback(err);
} else {
return callback(null, result);
}
});
}

// Функция для получения музыканта по id
function getMusicianById(id, callback) {
connection.query(“SELECT * FROM users WHERE id=?”, [id], (err, result) => {
if (err) {
console.error("Ошибка при получении музыканта с id {id}: ", err);
return callback(err);
} else {
return callback(null, result[0]);
}
});
}

function requireLogin(req, res, next) {
if (req.session.musicianId) {
next();
} else {
res.redirect("/login");
}
}

function search(query = '', role = '', city = '', genre = '') {
let results = [];

if (query || role || city || genre) {
const queryValues = [
'%{query.toLowerCase()}%’,
role === ‘’ ? null : role,
city === ‘’ ? null : city.toLowerCase().trim(),
genre === ‘’ ? null : genre.toLowerCase()
];

const queryConditions = [
‘name LIKE ? OR genre LIKE ?’,
‘role = ?’,
‘city = ?’,
‘genre = ?’
].filter(condition => queryValues[queryConditions.indexOf(condition)] !== null);

const sql = SELECT * FROM users WHERE ${queryConditions.join(' AND ')};

connection.query(sql, queryValues, (err, result) => {
if (err) {
console.error(‘Ошибка при поиске: ‘, err);
return results;
} else {
results = result.map(musician => {
return {
name: musician.name,
genre: musician.genre,
originalName: musician.name,
profileLink: /profile/${musician.id},
thumbnail: musician.thumbnail,
soundcloud: musician.soundcloud,
role: musician.role,
city: musician.city
};
}).sort((a, b) => {
const aNameScore = a.name.toLowerCase().startsWith(query) ? 2 : a.name.toLowerCase().includes(query) ? 1 : 0;
const bNameScore = b.name.toLowerCase().startsWith(query) ? 2 : b.name.toLowerCase().includes(query) ? 1 : 0;
const aGenreScore = a.genre.toLowerCase().startsWith(query) ? 2 : a.genre.toLowerCase().includes(query) ? 1 : 0;
const bGenreScore = b.genre.toLowerCase().startsWith(query) ? 2 : b.genre.toLowerCase().includes(query) ? 1 : 0;

// Sort by name score, then genre score, then location score (descending)
if (aNameScore + aGenreScore + a.city < bNameScore + bGenreScore + b.city) {
return 1;
} else if (aNameScore + aGenreScore + a.city > bNameScore + bGenreScore + b.city) {
return -1;
} else {
return 0;
}

});

// Remove duplicates
results = results.filter((result, index, self) =>
index === self.findIndex(r => (
r.name === result.name && r.genre === result.genre && r.city === result.city
))
);

return results;
}
});
}

app.use((req, res, next) => {
if (req.session.musicianId) {
getMusicianById(req.session.musicianId, (err, musician) => {
if (err) {
console.error(“Ошибка при получении current user: “, err);
} else {
res.locals.musician = musician;
res.locals.userLoggedIn = true;
res.locals.username = musician.name;
}
});
} else {
res.locals.userLoggedIn = false;
}
next();
});

app.get(”/”, (req, res) => {
getLastNRegisteredMusicians(5, (err, lastRegisteredMusicians) => {
if (err) {
console.error("Ошибка при получении последних зарегистрированных музыкантов: ", err);
res.status(500).send(“Ошибка получения данных”);
} else {
res.render(“index”, { musicians: lastRegisteredMusicians, query:’’,city:’‘,role:’‘,genre:’’ });
}
});
});

app.get(“/autocomplete/cities”, async (req, res) => {
const searchString = req.query.term;

connection.query(
“SELECT city FROM users WHERE city LIKE ?”,
[searchString + ‘%’],
(error, results, fields) => {
if (error) {
console.error(“Ошибка выполнения запроса: “, error);
res.status(500).send(“Ошибка выполнения запроса”);
} else {
const cities = results.map(row => row.city);
res.json(cities);
}
}
);
});

app.get(”/register”, (req, res) => {
if (req.session.musicianId) {
const musician = getMusicianById(req.session.musicianId);
res.redirect(“/profile/” + musician.id);
} else {



res.render(“register”, { citiesAndRegions, city:‘’, query:‘’,role:‘’ });
}
});

app.post(“/register”, (req, res) => {
if (req.session.musicianId) {
getMusicianById(req.session.musicianId, (err, musician) => {
if (err) {
console.error(“Ошибка при получении музыканта: “, err);
} else {
res.redirect(”/profile/” + musician.id);
}
});
} else {
const newMusician = {
name: req.body.name,
genre: req.body.genre,
instrument: req.body.instrument,
soundcloud: req.body.soundcloud,
password: req.body.password,
role: req.body.role,
city: req.body.city,
login: req.body.login,
};

if (req.files && req.files.thumbnail) {
const file = req.files.thumbnail;
const filename = “musician_” + file.name;
file.mv(“./public/img/” + filename);
newMusician.thumbnail = filename;
}

connection.query(“INSERT INTO users SET ?”, newMusician, (err, result) => {
if (err) {
console.error(“Ошибка при регистрации нового музыканта: “, err);
res.status(500).send(“Ошибка регистрации”);
} else {
req.session.musicianId = result.insertId;
res.redirect(”/profile/” + result.insertId);
}
});
}
});

app.get(“/profile/:id”, (req, res) => {
const musician = getMusicianById(parseInt(req.params.id));

if (musician) {
res.render(“profile”, { musician: musician, city:‘’, query:‘’, role:‘’ });
} else {
res.status(404).send(“Musician not found”);
}
});

app.get(“/login”, (req, res) => {
res.render(“login”);
});

app.post(“/login”, (req, res) => {
connection.query(“SELECT * FROM users WHERE login=? AND password=?”, [req.body.login, req.body.password], (err, result) => {
if (err) {
console.error(“Ошибка при входе: “, err);
res.status(500).send(“Ошибка при входе”);
} else {
if (result.length > 0) {
req.session.musicianId = result[0].id;
res.redirect(”/profile/” + result[0].id);
} else {
res.render(“login”, { error: “Invalid login or password” });
}
}
}
);
});

app.get(“/logout”, (req, res) => {
req.session.destroy();
res.redirect(“/”);
});

app.get(‘/search’, (req, res) => {
const query = req.query.query || ‘’;
const role = req.query.role || ‘’;
const city = req.query.city || ‘’;
const genre = req.query.genre || ‘’;

let musicians = [];

if (query || role || city || genre) {
musicians = search(query, role, city, genre);
} else {
const data = fs.readFileSync(‘./db/musicians.json’);
musicians = JSON.parse(data).musicians.map(musician => {
return {
name: musician.name,
genre: musician.genre,
originalName: musician.name,
profileLink: /profile/${musician.id},
thumbnail: musician.thumbnail,
soundcloud: musician.soundcloud,
role: musician.role,
city: musician.city
};
});
}

//res.locals.predefinedGenres = predefinedGenres;
app.locals.JSON = JSON;
res.render(‘search’, { musicians, query, role, city, genre, citiesAndRegions});

//res.redirect(‘/search’);
});

app.get(“/profile/:id/edit”, requireLogin, (req, res) => {
const musician = getMusicianById(parseInt(req.params.id));

if (musician) {
if (req.session.musicianId === musician.id) { // Check if the logged-in user is the owner of the profile
res.render(“edit-profile”, { musician: musician });
} else {
res.status(403).send(“Access denied”);
}
} else {
res.status(404).send(“Musician not found”);
}
});





app.post(“/profile/:id/edit”, requireLogin, (req, res) => {
const musicianId = parseInt(req.params.id);

getMusicianById(musicianId, (err, musician) => {
if (err) {
console.error(“Ошибка при получении музыканта: “, err);
res.status(500).send(“Ошибка при получении данных”);
} else {
if (musician) {
const updatedMusician = {
name: req.body.name,
genre: req.body.genre,
instrument: req.body.instrument,
soundcloud: req.body.soundcloud,
soundcloud1: req.body.soundcloud1,
soundcloud2: req.body.soundcloud2,
city: req.body.city,
role: req.body.role,
bio: req.body.bio,
};

if (req.files && req.files.thumbnail) {
const file = req.files.thumbnail;
const filename = “musician_” + musicianId + “_” + file.name;
file.mv(”./public/img/” + filename);
updatedMusician.thumbnail = filename;
}

connection.query(“UPDATE users SET ? WHERE id=?”, [updatedMusician, musicianId], (err, result) => {
if (err) {
console.error(“Ошибка при обновлении профиля музыканта: “, err);
res.status(500).send(“Ошибка при обновлении профиля”);
} else {
res.redirect(”/profile/” + musicianId);
}
});
} else {
res.status(404).send(“Musician not found”);
}
}
});
});

function isValidSoundCloudUrl(url) {
return url.startsWith(‘https://soundcloud.com/’);
}

app.listen(3000, () => {
console.log(“Server started on port 3000”);
});

error:C:\Users\Ilya\Downloads\my-musician-network\app.js:383



SyntaxError: Unexpected end of input

я пропустил где-то пару скобочек