Whats causing this error? TypeError: Client.__init__() missing 1 required keyword-only argument: 'intents' - discord

Whats causing this error?
TypeError: Client.init() missing 1 required keyword-only argument: 'intents'
Here is my code below
## install discord.py
## py -3 -m pip install -U discord.py
## install requests
## py -3 -m pip install -U requests
## install qbittorrent-api
## py -3 -m pip install -U qbittorrent-api
import discord
from discord.ext import commands
import requests
import qbittorrentapi
def filterBy(TorrentInfo,filterType):
if TorrentInfo[1]==filterType or filterType=="all":
return True
else:
return False
def filterList(FullList,filterType):
FilteredList=[]
for i in range(len(FullList)):
if filterBy(FullList[i],filterType):
FilteredList.append(FullList[i])
SortedList=[]
for i in range(len(FilteredList)):
if FilteredList[i][2]!="100%":
SortedList.append(FilteredList[i])
SortedList.sort(key=lambda x:float(x[2][:-1]),reverse=True)
for i in range(len(FilteredList)):
if FilteredList[i][2]=="100%":
SortedList.append(FilteredList[i])
return SortedList
def renameStates(FullList):
completedList=["uploading","pausedUP","checkingUP","stalledUP","forcedUP"]
downloadingList=["downloading"]
missingList=["missingFiles"]
stalledList=["stalledDL"]
metaList=["metaDL"]
queuedList=["queuedDL"]
pausedList=["pausedDL"]
for i in range(len(FullList)):
if FullList[i][3] in completedList:
FullList[i][3]=StatusList[0]
elif FullList[i][3] in downloadingList:
FullList[i][3]=StatusList[1]
elif FullList[i][3] in missingList:
FullList[i][3]=StatusList[2]
elif FullList[i][3] in stalledList:
FullList[i][3]=StatusList[3]
elif FullList[i][3] in metaList:
FullList[i][3]=StatusList[4]
elif FullList[i][3] in queuedList:
FullList[i][3]=StatusList[5]
elif FullList[i][3] in pausedList:
FullList[i][3]=StatusList[6]
else:
FullList[i][3]=StatusList[7]
return FullList
def findCompleted(FullList):
CompletedList=[]
for i in range(len(FullList)):
if FullList[i][3]==StatusList[0]: #Completed
CompletedList.append(FullList[i])
return CompletedList
def findDownloading(FullList):
DownloadingList=[]
for i in range(len(FullList)):
if FullList[i][3]==StatusList[1]: #Downloading
DownloadingList.append(FullList[i])
elif FullList[i][3]==StatusList[3]: #Stalled
DownloadingList.append(FullList[i])
elif FullList[i][3]==StatusList[4]: #DownloadingMeta
DownloadingList.append(FullList[i])
elif FullList[i][3]==StatusList[5]: #Queued
DownloadingList.append(FullList[i])
elif FullList[i][3]==StatusList[6]: #Paused
DownloadingList.append(FullList[i])
return DownloadingList
def convertToDiscord(InfoList):
if not InfoList:
return NothingDownloading
maxCharsDiscord=1700
FinalList=[]
indexRange=[2,3,4,0]
for i in range(len(InfoList)):
FinalList.append([])
for j in range(len(indexRange)):
if InfoList[i][indexRange[j]]!="inf":
FinalList[i].append(InfoList[i][indexRange[j]])
StringListTwo=convertToString(FinalList)
StringList=convertToString(FinalList)
currentLength=len(StringList)
currentMsg=[]
while currentLength>0:
maxLength=StringList[0:maxCharsDiscord].count('\n')
numChars=findNth(StringList,'\n',maxLength)
if(StringList[numChars+1:-1].count('\n'))==0:
currentMsg.append(StringList[:])
else:
currentMsg.append(StringList[0:numChars])
StringList=StringList[numChars+1:-1]
currentLength=currentLength-maxCharsDiscord
return currentMsg
def findNth(String,Substring,Occurence):
val = -1
for i in range(0, Occurence):
val = String.find(Substring, val + 1)
return val
def convertToString(nonStrList):
StringList=str(nonStrList)
if StringList.find(ListSeparator)==-1:
StringList=StringList.replace("'], ['","\n\n")
StringList=StringList.replace("']]","")
StringList=StringList.replace("[['","")
StringList=StringList.replace("', '",ListSeparator)
else:
StringList=StringList.replace("', '","\n\n")
StringList=StringList.replace("']","")
StringList=StringList.replace("['","")
return StringList
def printMessages(DiscordLists):
if DiscordList!=NothingDownloading:
for i in range(len(DiscordLists)):
print(convertToString(DiscordLists[i]))
print("------------------------------------------------")
else:
print(NothingDownloading)
print("------------------------------------------------")
StatusList = ["Completed","Downloading","Files missing","Stalled","Attempting to start","Queued","Paused","Unknown status"]
ListSeparator = ", "
NothingDownloading = "Nothing is downloading! Why not request something?"
DownloadingStatus = "downloading"
CompleteStatus = "completed"
#############################
## ENTER YOUR DETAILS HERE ##
#############################
botChannel = "BOT CHANNEL" ## ID CHANNEL OF THE CHANNEL FOR THE BOT TO LISTEN TO ##
tvCategory = "tv-sonarr" ## CATEGORY IN QBIT FOR TV SHOWS ##
movieCategory = "radarr" ## CATEGORY IN QBIT FOR MOVIES ##
qbt_client = qbittorrentapi.Client(host='localhost', port=8080, username='admin', password='password') ## QBIT WEB LOGIN DETAILS ##
TOKEN = "BOT SECRET" ## DISCORD BOT SECRET ##
#############################
#############################
#############################
# the Client will automatically acquire/maintain a logged in state in line with any request.
# therefore, this is not necessary; however, you may want to test the provided login credentials.
try:
qbt_client.auth_log_in()
except qbittorrentapi.LoginFailed as e:
print(e)
def updateTorrentList():
counter = 0
TorrentList=[]
for torrent in qbt_client.torrents_info():
TempList=[]
TempList.append(torrent.name)
TempList.append(torrent.category)
TempList.append(str(round(torrent.progress*100,2))+"%")
TempList.append(torrent.state)
TempList.append(convertTime(torrent.eta))
TorrentList.append(TempList)
counter=counter+1
return TorrentList
def convertTime(seconds):
intervals = (
('weeks', 604800), # 60 * 60 * 24 * 7
('days', 86400), # 60 * 60 * 24
('hours', 3600), # 60 * 60
('minutes', 60),
('seconds', 1),)
if seconds!=8640000:
result = []
for name, count in intervals:
value = seconds // count
if value:
seconds -= value * count
if value == 1:
name = name.rstrip('s')
result.append("{} {}".format(value, name))
return 'ETA: '+', '.join(result[:])
else:
return "inf"
def updateAll(category,status="all"):
TorrentList=updateTorrentList()
FilteredList = filterList(TorrentList,category)
FinalList=renameStates(FilteredList)
if status==DownloadingStatus:
FinalList=findDownloading(FinalList)
elif status==CompleteStatus:
FinalList=findCompleted(FinalList)
DiscordList=convertToDiscord(FinalList)
return DiscordList
print("------------------------------------------------")
print("starting Discord...")
client = discord.Client()
prefix = "$"
bot=commands.Bot(command_prefix=prefix)
## BOT VERSION ##
#bot.event
async def on_ready():
print('We have logged in as {0.user}'.format(bot))
print("------------------------------------------------")
#bot.event
async def on_message(message):
if message.author == bot.user:
return
await bot.process_commands(message)
#bot.command(
help = "Use this to see the status of what's currently downloading."+"\n"+"If you want to get fancy, you can search for movies/tv shows specifically by type $status movies or $status tv."+"\n"+"You can also see what's completed by doing $status completed, or $status all to see everything."+"\n"+"Finally, you can combine these (like $status tv completed) to only see completed tv shows."+"\n"+"(tip: you can see everything by typing $status all)",
brief = "Use this to see what's currently downloading"
)
async def status(ctx, *args):
channelID=ctx.message.channel.id
if botChannel==channelID:
def not_pinned(message):
return not message.pinned
await ctx.message.channel.purge(check=not_pinned)
if "all" in args:
updateStatus="all"
elif "completed" in args:
updateStatus=CompleteStatus
else:
updateStatus=DownloadingStatus
if "movies" in args:
Category=movieCategory
elif "tv" in args:
Category=tvCategory
else:
Category="all"
DiscordList=updateAll(Category,updateStatus)
if DiscordList!=NothingDownloading:
for i in range(len(DiscordList)):
await ctx.channel.send(DiscordList[i])
else:
await ctx.channel.send(NothingDownloading)
bot.run(TOKEN)
can't get my discordbot to run. it worked in the past, but stopped working. it's job is to allow the user to check the status of a requested media download. any help would be greatly appreciated.

versions of discord.py 2.0 and above require the argument intents.
prefix = "$"
bot=commands.Bot(command_prefix=prefix, intents=discord.Intents.all())
Adding intents is must for the bot to work.
you can learn more about intents at https://discordpy.readthedocs.io/en/latest/intents.html?highlight=intents

Related

Command raised an exception: TypeError: Object of type File is not JSON serializable but no other solution working for me

The Function of discord command named server
#bot.command(name = 'server')
async def _minecraftserverinfo(ctx, ip:str, port:str, servername:str):
if servername == "survival":
svname = "Survival"
elif servername == "lobby":
svname = "Lobby"
#serverembed = createEmbed(ip, port)
#value = f"The server has {status.players.online} players and replied in {status.latency} ms\nThe server replied in {latency} ms\nThe server has the following players online: {','.join(query.players.names)}"
server = MinecraftServer.lookup(ip+':'+port)
#=======================================
#=======================================
# 'status' is supported by all Minecraft servers that are version 1.7 or higher.
status = server.status()
latency = server.ping()
query = server.query()
serverembed = discord.Embed(title = ip, url = "https://www.zer02infinity.com/",description = f"Zero To Infinity Minecraft {svname} Server")#\nThe server has the following players online: {','.join(query.players.names)}")
serverembed.set_thumbnail(url="https://cdn.discordapp.com/attachments/833829693588373534/920017091325747220/2021-12-13_11.png")
serverembed.add_field(name="Players Count", value=f"{status.players.online}/{query.players.max}", inline=True)
serverembed.add_field(name="Direct Connect:", value=f"```mc.zer02infinity.com```", inline=True)
#serverembed.add_field(name="Names:", value=f"{latency} ms", inline=True)
#nl = '\n'
#serverembed.add_field(name="Names:", value=f"{nl}{nl.join(query.players.names)}", inline=False)
#serverembed.add_field(name="Names:", value={'\n'.join(query.players.ping)}, inline=True)
#sending embed
embed = await ctx.send(embed=serverembed)
await embed.add_reaction(emoji)
message_id = embed.id
while True:
server = MinecraftServer.lookup(ip+':'+port)
# 'status' is supported by all Minecraft servers that are version 1.7 or higher.
status = server.status()
latency = server.ping()
query = server.query()
serverembed = discord.Embed(title = ip, url = "https://www.zer02infinity.com/",description = f"Zero To Infinity Minecraft {svname} Server")#\nThe server has the following players online: {','.join(query.players.names)}")
serverembed.set_thumbnail(url="https://cdn.discordapp.com/attachments/833829693588373534/920017091325747220/2021-12-13_11.png")
serverembed.add_field(name="Players Count", value=f"{status.players.online}/{query.players.max}", inline=True)
serverembed.add_field(name="Direct Connect:", value=f"```mc.zer02infinity.com```", inline=True)
#serverembed.add_field(name="Names:", value=f"{latency} ms", inline=True)
#nl = '\n'
problem started after i added a image from local file
file = discord.File("./foo.png", filename="foo.png")
serverembed.add_field(name="Names:", value={','.join(query.players.names)}, inline=False)
serverembed.set_image(url="attachment://foo.png")
#print('Winners are:', *names, sep='\n')
serverembed = await embed.edit(file=file, embed = serverembed)
await asyncio.sleep(60)
pass
So this is the recent code i added where foo.png is maintained by graph.py given below
import discord
from discord.ext import commands
import matplotlib.pyplot as plt
class Equations(commands.Cog):
def __init__(self, bot):
self.bot = bot
def plotlineareq(self, a, b, clr):
x = [0, 10]
y = [(a * i + b) for i in x]
plt.figure(figsize=(10, 10)) # #Size of Graph
plt.xlim(x) # #X Range [-6,6]
plt.ylim(x) # #Y Range [-6,6]
axis = plt.gca() # #Get Current Axis
plt.plot(axis.get_xlim(), [0, 0], 'k--') # #X Axis Plots Line Across
plt.plot([0, 0], axis.get_ylim(), 'k--') # #Y Axis Plots Line Across
plt.locator_params(axis="x", nbins=20)
plt.locator_params(axis="y", nbins=20)
plt.plot(x, y, label='linear', linestyle='solid', color=clr)
plt.ylabel('Players')
plt.xlabel('Time')
mm = str(a)
bb = str(b)
plt.title('Live Status')
#plt.grid()
plt.savefig("foo.png")
#commands.command()
async def linear(self, ctx, equation):
try:
equation = equation.replace(" ", "")
mx = equation.split("x")[0]
mx = equation.replace("x", "").replace("y=", "")
bx = equation.split("+")[1]
self.plotlineareq(mx, bx, 'b')
file = discord.File("foo.png", filename='foo.png')
embed = discord.Embed(color=0xff0000)
embed = embed.set_image(url="attachment://foo.png")
await ctx.send(file=file, embed=embed)
except Exception as e:
await ctx.send(f"An error occured: {e}")
def setup(bot):
bot.add_cog(Equations(bot))
After executing it gives the following error in error log-
Command raised an exception: TypeError: Object of type File is not JSON serializable

(Discord.py) Send a dm or is to all members of all servers

I begin the dev for 2 days and i want to create a command in the dm of the bot ">
#bot.event
async def on_message(message):
if message.content.startswith('><dmall'):
name = message.content.split(" ")[1]
if(name == "all"):
for member in message.guild.members:
try:
await member.send("test")
except discord.Forbidden:
print("[DM]" + name + "à bloqué ses dm")
else:
member = discord.utils.get(message.guild.members, name=name)
NOTE: PLEASE DO NOT ABUSE THIS, IT IS A BANNABLE OFFENSE ON DISCORD'S TOS
# an alternative to putting your commands in an on_message event:
#bot.command()
async def dmall(ctx):
for m in bot.get_all_members():
await m.send("Hello! This is a DM :)")
print("Done!")
# error handler
#bot.event
async def on_command_error(ctx, error):
if isinstance(error, discord.ext.commands.errors.Forbidden):
print(f"[DM] {ctx.author} has DMs disabled.")
else:
print(error)
References:
Client.get_all_members()
discord.on_command_error()
Exceptions

WatsonApiException: Error: invalid-api-key, Code: 401

I cant find Alchemy Language API in IBM Watson.
Can I do this with natural-language-understanding service and how?
When I add
from watson_developer_cloud import NaturalLanguageUnderstandingV1
from watson_developer_cloud.natural_language_understanding_v1 \
import Features, EntitiesOptions, KeywordsOptions
It shows some error with combined keyword
# In[]:
import tweepy
import re
import time
import math
import pandas as pd
from watson_developer_cloud import AlchemyLanguageV1
def initAlchemy():
al = AlchemyLanguageV1(api_key='GRYVUMdBbOtJXxNOIs1aopjjaiyOmLG7xJBzkAnvvwLh')
return al
def initTwitterApi():
consumer_key = 'OmK1RrZCVJSRmKxIuQqkBExvw'
consumer_secret = 'VWn6OR4rRgSi7qGnZHCblJMhrSvj1QbJmf0f62uX6ZQWZUUx5q'
access_token = '4852231552-adGooMpTB3EJYPHvs6oGZ40qlo3d2JbVjqUUWkJ'
access_token_secret = 'm9hgeM9p0r1nn8IoQWJYBs5qUQu56XmrAhsDSYKjuiVA4'
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
return api
'''This function is implemented to handle tweepy exception errors
because search is rate limited at 180 queries per 15 minute window by twitter'''
def limit(cursor):
while True:
try:
yield cursor.next()
except tweepy.TweepError as error:
print(repr(error))
print("Twitter Request limit error reached sleeping for 15 minutes")
time.sleep(16*60)
except tweepy.RateLimitError:
print("Rate Limit Error occurred Sleeping for 16 minutes")
time.sleep(16*60)
def retrieveTweets(api, search, lim):
if(lim == ""):
lim = math.inf
else:
lim = int(lim)
text = []
for tweet in limit(tweepy.Cursor(api.search, q=search).items(limit = lim)):
t = re.sub('\s+', ' ', tweet.text)
text.append(t)
data = {"Tweet":text,
"Sentiment":"",
"Score":""}
dataFrame = pd.DataFrame(data, columns=["Tweet","Sentiment","Score"])
return dataFrame
def analyze(al,dataFrame):
sentiment = []
score = []
for i in range(0, dataFrame["Tweet"].__len__()):
res = al.combined(text=dataFrame["Tweet"][i],
extract="doc-sentiment",
sentiment=1)
sentiment.append(res["docSentiment"]["type"])
if(res["docSentiment"]["type"] == "neutral"):
score.append(0)
else:
score.append(res["docSentiment"]["score"])
dataFrame["Sentiment"] = sentiment
dataFrame["Score"] = score
return dataFrame
def main():
#Initialse Twitter Api
api = initTwitterApi()
#Retrieve tweets
dataFrame = retrieveTweets(api,input("Enter the search query (e.g. #hillaryclinton ) : "), input("Enter limit for number of tweets to be searched or else just hit enter : "))
#Initialise IBM Watson Alchemy Language Api
al = initAlchemy()
#Do Document Sentiment analysis
dataFrame = analyze(al, dataFrame)
#Save tweets, sentiment, and score data frame in csv file
dataFrame.to_csv(input("Enter the name of the file (with .csv extension) : "))
if __name__ == '__main__':
main()# -*- coding: utf-8 -*-
The Watson Natural Language Understanding only has a combined call, but since it is the only call, it isn't called combined, its actually analyze. Best place to go for details would be the API documentation - https://www.ibm.com/watson/developercloud/natural-language-understanding/api/v1/?python#post-analyze

mk livestatus LQL: Select Nagoios service both in CRITICAL and Hard state

Following example script can pick out CRITICAL service but it also will select CRITICAL service in both SOFT and HARD state. I read though R1 doc many times. Still failed to select service in HARD and CRITICAL state.
#!/usr/bin/python
import socket
socket_path = '/var/spool/nagios/cmd/livestatus'
def sendQuery(query):
"""
INPUT: LQL string.
OUPUT: query result in string.
REF : http://stackoverflow.com/questions/24730883/python-errno-23-socket-livestatus
"""
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(socket_path)
s.send(query)
s.shutdown(socket.SHUT_WR)
answer = ''
while True:
data = s.recv(1024)
answer += data
if len(data) < 1024:
break
s.close()
return answer
LQL = 'GET services\n' + \
'Columns: host_name description state last_state_change last_time_critical\n' + \
'Filter: scheduled_downtime_depth = 0 \n' + \
'Filter: host_scheduled_downtime_depth = 0\n' + \
'Filter: in_notification_period = 1\n' + \
'Filter: state = 2 \n'
print sendQuery(LQL)
R1: https://mathias-kettner.de/checkmk_livestatus.html
Answer was provided by livestatus community, See R1.
select_type = 1 where 1 = HARD service alert. 0 = SOFT.
R1: http://lists.mathias-kettner.de/pipermail/checkmk-en/2016-January/018483.html

Python flask web application with multilanguages support by host and prefix

I have one server with flask application instance and have several domain which mapped to this server by DNS.
My site must support several languages by host and prefix:
mysite.com - english
mysite.com/fr - franch
mysite.ru - russian
mysite.ru/by - belarusian
localhost or other unknown host without language prefix - default language (english)
I implemented it with double route registration /endpoint and /<lang>/endpoint and reloaded url_for function and it work, but now I must implement custom error pages for abort function:
mysite.com/wrong-url-there - mysite.com/404.html (english)
mysite.com/fr/wrong-url-there - mysite.com/fr/404.html (franch)
mysite.ru/wrong-url-there - mysite.ru/404.html (russian)
mysite.ru/by/wrong-url-there - mysite.ru/by/404.html (belorusian)
And I don't see solution for this.
I think my implementation bad and I must improve it. I think I must create one instance of application for each site language root with predefined language for it or use blueprint, but I don't find solution for me yet.
Is anybody can give me advice how resolve this url multilanguages support with flask or wsgi or nginx?
It's in the official doc: http://flask.pocoo.org/docs/patterns/urlprocessors/ (This is basically the same answer as Matthew Scragg's).
I worked on something similar few months back. I modified it a bit and pushed to github.
You can do what codegeek suggested if you are unable to make your templates language neutral. With this method you can cut down on the template files needed.
https://github.com/scragg0x/Flask-Localisation-Example
mysite.py
from flask import Flask, Blueprint, g, redirect, request
app = Flask(__name__)
mod = Blueprint('mysite', __name__, url_prefix='/<lang_code>')
sites = {
'mysite.com': 'en',
'myothersite.com': 'fr'
}
#app.url_defaults
def add_language_code(endpoint, values):
values.setdefault('lang_code', g.lang_code)
#app.url_value_preprocessor
def pull_lang_code(endpoint, values):
url = request.url.split('/', 3)
g.lang_code = sites[url[2]]
#mod.url_defaults
def add_language_code(endpoint, values):
values.setdefault('lang_code', g.lang_code)
#mod.url_value_preprocessor
def pull_lang_code(endpoint, values):
g.lang_code = values.pop('lang_code')
#app.route('/')
#mod.route('/')
def index():
# Use g.lang_code to pull localized data for template
return 'lang = %s' % g.lang_code
app.register_blueprint(mod)
tests.py
import os
import unittest
import re
import requests
import urllib2
import json
from mysite import app
class MySiteTestCase(unittest.TestCase):
def setUp(self):
app.config['TESTING'] = True
app.config['SERVER_NAME'] = 'mysite.com'
self.domain = 'http://mysite.com/'
self.app = app.test_client()
def tearDown(self):
pass
def test_en_index(self):
rv = self.app.get('/en/', self.domain)
self.assertEqual(rv.data, 'lang = en')
print self.domain, rv.data
def test_fr_index(self):
rv = self.app.get('/fr/', self.domain)
self.assertEqual(rv.data, 'lang = fr')
print self.domain, rv.data
def test_default(self):
rv = self.app.get('/', self.domain)
self.assertEqual(rv.data, 'lang = en')
print self.domain, rv.data
class MyOtherSiteTestCase(unittest.TestCase):
def setUp(self):
app.config['TESTING'] = True
app.config['SERVER_NAME'] = 'myothersite.com'
self.domain = 'http://myothersite.com/'
self.app = app.test_client()
def tearDown(self):
pass
def test_en_index(self):
rv = self.app.get('/en/', self.domain)
self.assertEqual(rv.data, 'lang = en')
print self.domain, rv.data
def test_fr_index(self):
rv = self.app.get('/fr/', self.domain)
self.assertEqual(rv.data, 'lang = fr')
print self.domain, rv.data
def test_default(self):
rv = self.app.get('/', self.domain)
self.assertEqual(rv.data, 'lang = fr')
print self.domain, rv.data
if __name__ == '__main__':
unittest.main()
Disclaimer: This code is not tested. I am just giving you a ballpark idea of how to approach this.
I suggest you use blueprints in combination with an extension like Flask-Babel. For example, you can do something like:
views.py
mysitebp = Blueprint('mysitebp',__name__)
Then in your application package (usually __init__.py) , you can do:
__init__.py
from mysite.views import mysitebp
app = Flask(__name__)
app.register_blueprint(mysitebp,url_prefix='/en/',template_folder='en')
app.register_blueprint(mysitebp,url_prefix='/fr',template_folder='fr')
..and so on
Your directory structure could look like:
mysite/
__init__.py
views.py
templates/
base.html
404.html
en/
en.html
fr/
french.html
Flask-Babel would help you translate the 404.html etc.
My own solution:
from flask import Flask, g, render_template, redirect, request
app = Flask(__name__)
default_language = 'en'
language_urls = {
'en': 'mysite.com',
'fr': 'mysite.com/fr',
'ru': 'mysite.ru',
'by': 'mysite.ru/by',
}
languages = ','.join(language_urls.keys())
def get_language_by_request(request_host, request_path):
'''
Looking bad, but work.
I cab't use request.view_args there,
because this can't detect language for 404 pages
like mysite.com/fr/unknown-page
'''
request_host_path = request_host + request_path
request_paths = request_host_path.split('/', 2)
if (len(request_paths) > 1 and request_paths[1] in language_urls.keys()):
request_language_prefix = request_paths[1]
return request_language_prefix
for language, url in language_urls.items():
host_prefix = url.split('/')
if len(host_prefix) == 1:
host, = host_prefix
if request_host == host:
return language
return default_language
def get_language_url_parameter_value(language, request_host):
host_prefix = language_urls[language]
if host_prefix == request_host:
return None
return language
def get_redirection_url_by_request(request_host, request_path, request_url):
'''
Looking bad, but work.
I cab't use request.view_args there,
because this can't detect language for 404 pages
like mysite.com/fr/unknown-page
'''
request_host_path = request_host + request_path
request_paths = request_host_path.split('/', 2)
request_language_prefix = None
if (len(request_paths) > 1 and request_paths[1] in language_urls.keys()):
request_language_prefix = request_paths[1]
hosts = []
for language, url in language_urls.items():
host_prefix = url.split('/')
if len(host_prefix) == 1:
host, = host_prefix
language_prefix = None
else:
host, language_prefix = host_prefix
if request_host == host and request_language_prefix == language_prefix:
return None
hosts.append(host)
if request_host not in hosts:
return None
if request_language_prefix:
request_host_prefix = request_host + '/' + request_language_prefix
host_prefix = language_urls[request_language_prefix]
return request_url.replace(request_host_prefix, host_prefix)
return None
#app.url_defaults
def set_language_in_url(endpoint, values):
if '_lang' not in values and hasattr(g, 'language_url_value'):
values['_lang'] = g.language_url_value
#app.url_value_preprocessor
def get_language_from_url(endpoint, values):
g.language = get_language_by_request(request.host, request.path)
g.language_url_value = get_language_url_parameter_value(g.language, request.host)
if values and '_lang' in values:
del values['_lang']
#app.before_request
def check_language_redirection():
redirection_url = get_redirection_url_by_request(request.host, request.path, request.url)
return redirect(redirection_url) if redirection_url else None
#app.route('/')
#app.route('/<any(%s):_lang>/' % languages)
def home():
return render_template('home.html')
#app.route('/other/')
#app.route('/<any(%s):_lang>/other/' % languages)
def other():
return render_template('other.html')
I don't use blueprints there because I also use flask-login and I can't set several login pages with different languages for each blueprint. For example if page required login, flask redirect me to login page and I must update language for this page. Also login pages can't be as mysite.com/login, mysite.com/fr/login and etc without several redirections.
UPD: I can't use request.view_args for detect language or redirection, because on this case I can't detect language for error pages as mysite.com/fr/wrong-page-there (can't detect endpoint and view_args). To avoid this problem I can use hask: add url rule as /<lang_code>/<path:path> and raise 404 error there.

Resources