# ESX

You will receive the script in [`keymaster.fivem.net`](https://keymaster.fivem.net/asset-grants) profile, after this click in blue "download" button.

After download, put the script in your server files.

{% hint style="warning" %}
Remeber:

You need to be logged with the same cfx.re account you used to buy in my tebex store.
{% endhint %}

1. Install all [dependencies](#dependencies-part), and follow their respective installation instructions.

## Dependencies Part

* [**es\_extended**](https://github.com/ESX-Official/es_extended)
* [**oxmysql**](https://github.com/overextended/oxmysql)
* [**ox\_inventory**](https://github.com/overextended/ox_inventory) (for unique phones (**optional**))
* [**screenshot-basic**](https://github.com/citizenfx/screenshot-basic)&#x20;
* **qb-lapraces (**&#x50;rovided on downloaded file&#x73;**)**
* **qb-input (**&#x50;rovided on downloaded file&#x73;**)**
* [**xsound**](https://github.com/Xogy/xsound)

Download all the scripts by clicking on their respective names, put them in the server files and ensure in server.cfg

## Webhooks

JPR Phone System uses webhooks for photo system, video system and audios files.\
All you need to do is replace the default webhooks, via config.lua\
\
Our log system works for regular players as well as more detailed logs for staff.

<figure><img src="https://3317815405-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FAcw6nAW8IGe15skCfMoj%2Fuploads%2F7AqHe6zeCeThuXFscKK6%2FCaptura%20de%20ecr%C3%A3%202023-05-25%20150122.png?alt=media&#x26;token=50e5c67e-ecea-4235-949e-b466fbc7527d" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
For more info how to create a discord webhook follow this tutorial:\
<https://www.youtube.com/watch?v=fKksxz2Gdnc&t=7s&ab_channel=NoIntroTutorials>
{% endhint %}

## Unique Phones

In the `config.lua` file, we have the `Config.UniquePhones` option.

The Phone System **only supports** this system on **ESX** if the server uses [**ox\_inventory**](#dependencies-part), otherwise you need to disable this option and use the normal system (global phones, i.e. each player with their own phone).

<figure><img src="https://3317815405-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FAcw6nAW8IGe15skCfMoj%2Fuploads%2FLeZP36vRvz17sVAuLW7m%2Fimage.png?alt=media&#x26;token=754d20b1-616c-4a68-b5ba-11c1fae1e63c" alt=""><figcaption></figcaption></figure>

## Integration with the home system

Due to the huge variety of home systems for ESX, if you want to make your system compatible with the phone system, please open a ticket on our discord, we will help you.

{% tabs %}
{% tab title="ESX Property" %}
Add this inside **server\_config** file of **Phone System**:

```lua
ESX.RegisterServerCallback('jpr-phonesystem:server:GetPlayerHouses', function(source, cb, serie)
    local src = source
    local Player = ESX.GetPlayerFromId(src)
    local MyHouses = {}
    local CitizenId = MySQL.Sync.fetchAll('SELECT * FROM jpr_phonesystem_base WHERE idtelemovel = ?', {serie})
    
    if (CitizenId[1]) then
        -- for housing system adaptation, please open a discord ticket and talk with us
        local pHouses = exports["esx_property"]:GetPlayerProperties(CitizenId[1].citizenid)
        
        if pHouses then
            for k, v in pairs(pHouses) do
                if (pHouses[k]) then
                    pHouses[k].house = pHouses[k].Name
                    pHouses[k].citizenid = pHouses[k].Owner
                    pHouses[k].HouseData = {
                        coords = {
                            enter = {
                                x = pHouses[k].Entrance.x,
                                y = pHouses[k].Entrance.y,
                            }
                        },
                        adress = pHouses[k].Name,
                    }
                    pHouses[k].tier = pHouses[k].Interior
                    pHouses[k].label = pHouses[k].Name
                end
            end
            cb(pHouses)
        else
            cb(nil)
        end
    else
        cb(nil)
    end
end)
```

{% endtab %}

{% tab title="JPR Housing" %}
Open **config.lua** of **Phone System** and change house name to this one:

```lua
Config.HouseScriptName = "jpr-housing"
```

{% endtab %}

{% tab title="Loaf Housing" %}
Add this inside **server\_config** file of **Phone System**:

```lua
ESX.RegisterServerCallback('jpr-phonesystem:server:GetPlayerHouses', function(source, cb, serie)
    local myHouses = {}
    local citizenId = MySQL.scalar.await('SELECT citizenid FROM jpr_phonesystem_base WHERE idtelemovel = ?', { serie })

    if not citizenId then
        return cb(nil)
    end

    local houses = MySQL.query.await("SELECT propertyid FROM loaf_properties WHERE owner = ?", { citizenId })

    for i = 1, #houses do
        local propertyId = houses[i].propertyid
        local house = exports.loaf_housing:GetHouse(propertyId)

        if house then
            myHouses[#myHouses+1] = {
                house = house.label,
                label = house.label,
                citizenid = citizenId,
                HouseData = {
                    coords = {
                        enter = {
                            x = house.entrance.x,
                            y = house.entrance.y,
                        },
                    },
                    adress = house.label,
                },
                tier = {
                    label = "??",
                }
            }
        end
    end

    cb(myHouses)
end)
```

{% endtab %}

{% tab title="Template" %}
This part is a template of our callback to house script owners being able to be supported by us, just need to adapt this little callback and everything will work perfect:\
(Can be added inside **server\_config**.lua of **Phone System** or directly on **Housing Script** server side.)

```lua
ESX.RegisterServerCallback('jpr-phonesystem:server:GetPlayerHouses', function(source, cb, serie)
    local src = source
    local Player = ESX.GetPlayerFromId(src)
    local MyHouses = {}
    local CitizenId = MySQL.Sync.fetchAll('SELECT * FROM jpr_phonesystem_base WHERE idtelemovel = ?', {serie})
    
    if (CitizenId[1]) then
        -- for housing system adaptation, please open a discord ticket and talk with us
        local pHouses = exports["esx_property"]:GetPlayerProperties(CitizenId[1].citizenid)
        
        if pHouses then
            for k, v in pairs(pHouses) do
                if (pHouses[k]) then
                    pHouses[k].house = pHouses[k].Name
                    pHouses[k].citizenid = pHouses[k].Owner
                    pHouses[k].HouseData = {
                        coords = {
                            enter = {
                                x = pHouses[k].Entrance.x,
                                y = pHouses[k].Entrance.y,
                            }
                        },
                        adress = pHouses[k].Name,
                    }
                    pHouses[k].tier = pHouses[k].Interior
                    pHouses[k].label = pHouses[k].Name
                end
            end
            cb(pHouses)
        else
            cb(nil)
        end
    else
        cb(nil)
    end
end)
```

{% endtab %}
{% endtabs %}

## MDT :warning:

MDT app has all its code open, the filtering part is in **openFunctions.js** and the part that takes information from **SQL** is in **client\_config** and **server\_config**. \
Any change to your **SQL** can affect the way **MDT** works, so if you have the **programming skills** to adapt it to your server or **it's already working** (most of them) use it, otherwise **disable it in the config**.

## Permissions to JPR Phone System

JPR Phone System needs permissions to record your voice, so you can send audio messages and record videos with audio by the phone.

If you receive a message like this, click **F8**, "**Allow**".

<figure><img src="https://3317815405-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FAcw6nAW8IGe15skCfMoj%2Fuploads%2FKSd1vSqz5cqlHNXm9VTQ%2F15.png?alt=media&#x26;token=8a14a8e0-7539-4539-aa4e-c9a5a3fb0646" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This message appears only once.
{% endhint %}

## SQL

Execute `JPR - Phone System.sql` file in your SQL

{% hint style="danger" %}
This is mandatory!
{% endhint %}

## Inventory

{% tabs %}
{% tab title="Usual Inventorys" %}
Dont need to do any changes, just be sure you have all phones items and powerbank item created on **SQL** `items` **Table.**
{% endtab %}

{% tab title="OX Inventory" %}
`ox_inventory - data - items.lua`, **replace** phone item and **add** powerbank item:

```lua
['phone'] = {
	label = 'Phone',
	weight = 190,
	stack = false,
	close = true,
},
['phone_white'] = {
	label = 'White Phone',
	weight = 190,
	stack = false,
	close = true,
},
['phone_gold'] = {
	label = 'Gold Phone',
	weight = 190,
	stack = false,
	close = true,
},
['phone_red'] = {
	label = 'Red Phone',
	weight = 190,
	stack = false,
	close = true,
},
['phone_blue'] = {
	label = 'Blue Phone',
	weight = 190,
	stack = false,
	close = true,
},
['phone_green'] = {
	label = 'Green Phone',
	weight = 190,
	stack = false,
	close = true,
},
['phone_pink'] = {
	label = 'Pink Phone',
	weight = 190,
	stack = false,
	close = true,
},
['phone_green_light'] = {
	label = 'Green Light Phone',
	weight = 190,
	stack = false,
	close = true,
},
["phone_purple"] = {
	label = "Purple Phone",
	weight = 1,
	stack = true,
	close = true,
},
["phone_purple_deep"] = {
	label = "Deep Purple Phone",
	weight = 1,
	stack = true,
	close = true,
},
['powerbank'] = {
	label = 'Powerbank',
	weight = 190,
	stack = false,
	close = false,
},
['phone_no_case'] = {
	label = 'No phone case',
	weight = 0,
	stack = false,
	close = true,
},
['phone_case_1'] = {
	label = 'Phone Case 1',
	weight = 190,
	stack = false,
	close = true,
},
['phone_case_2'] = {
	label = 'Phone Case 2',
	weight = 190,
	stack = false,
	close = true,
},
['phone_case_3'] = {
	label = 'Phone Case 3',
	weight = 190,
	stack = false,
	close = true,
},
['phone_case_4'] = {
	label = 'Phone Case 4',
	weight = 190,
	stack = false,
	close = true,
},
['phone_case_5'] = {
	label = 'Phone Case 5',
	weight = 190,
	stack = false,
	close = true,
},
['phone_case_6'] = {
	label = 'Phone Case 6',
	weight = 190,
	stack = false,
	close = true,
},
['phone_case_7'] = {
	label = 'Phone Case 7',
	weight = 190,
	stack = false,
	close = true,
},
['phone_case_8'] = {
	label = 'Phone Case 8',
	weight = 190,
	stack = false,
	close = true,
},
['phone_case_9'] = {
	label = 'Phone Case 9',
	weight = 190,
	stack = false,
	close = true,
},
['phone_case_10'] = {
	label = 'Phone Case 10',
	weight = 190,
	stack = false,
	close = true,
},

```

`ox_inventory  - client.lua`, **remove** this lines:

```lua
local phone = Items.phone

	if phone and phone.count < 1 then
		pcall(function()
			return exports.npwd:setPhoneDisabled(true)
		end)
	end
```

`ox_inventory - modules - items - client.lua`, **remove** this lines:

```lua
Item('phone', function(data, slot)
	local success, result = pcall(function()
		return exports.npwd:isPhoneVisible()
	end)

	if success then
		exports.npwd:setPhoneVisible(not result)
	end
end)
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
The default ESX inventory does not require any modification
{% endhint %}

## Using [Fivemanage](https://www.fivemanage.com/)

Follow this little video to know how to use [Fivemanage ](https://www.fivemanage.com/)for media uploads ( avoid discord future problems ) with our **Phone System**:

{% embed url="<https://www.youtube.com/watch?ab_channel=JPResources&v=XaV_jAJZDdI>" %}

(If you dont want this and keep "risking", we provide old system at same, just turn on **UseOtherUploadSystem** to true, **UseFivemerrSystem** to false and **UseFiveManageSystem** to false)

## Setup Google API Key

Just need to follow this quick 1 min video:

{% embed url="<https://www.youtube.com/watch?v=1Nbv3slB2ZU>" %}

{% hint style="danger" %}
Without this **Google API Key**, your **spotify and youtube WILL NOT WORK!!**
{% endhint %}

## Video tutorial

If you have trouble installing it after all the explanation, you can watch this video of the script installation:

[**Click me**](https://www.youtube.com/watch?v=YiixJhw1KbY) **( video 1 ) or** [**Click me**](https://www.youtube.com/watch?v=tGro1tqqCLM) **( video 2 ) or** [**Click me**](https://www.youtube.com/watch?v=mLETX6l318I) **( video 3)**
